C++ 可以有条件地向下转换 class 指针吗?

C++ can you downcast class pointer conditionally?

我有一个基础 class(机器人),根据传递给程序的参数,我想将机器人指针向下转换为特定的派生 class。机器人 class 具有在每个派生的 classes.

中定义的虚函数

到目前为止,我可以创建基 class 的指针,并在条件语句中创建派生的 class,然后将基动态转换为该指针。在条件中,指针按预期工作,但在离开条件语句后,派生的 class 超出范围,函数返回虚拟。有没有办法让指针指向派生的 class?

class vehicles{
    public:
        virtual void print_state(int state_ind, ofstream& file){}
};

class hovercraft : public vehicles{
    public:
        hovercraft(
            int L_in, int W_in, 
            double start_x, double start_y, 
            double goal_x, double goal_y)
        {
            L = L_in;
            W = W_in;
            start_state.x = start_x;
            start_state.y = start_y;
            goal_state.x = goal_x;
            goal_state.y = goal_y;
            Tree.push_back(start_state);
        }

        void print_state(int state_ind, ofstream& file){
            state s = Tree[state_ind];

            file<<s.phi<<","<<
                s.u<<","<<
                s.v<<","<<
                s.r<<","<<
                s.x<<","<<
                s.y<<"\n";
        }

    private:
        struct state{
            double g=0;
            double u=0;
            double v=0;
            double r=0;
            double x=0;
            double y=0;
            double phi=0;
            int p=0;
        };

        int L,W;
        state start_state, goal_state, state_sample;
        vector<state> Tree;
    };

int main(int argc, char* argv[])
{   
    ifstream infile;
    string vehicle_name;
    vehicles* vehicle;
    int start, goal;
    for(int i=0; i < argc; i++){
        if (string(argv[i])=="-m"){
            infile.open (argv[i+1]);
        } else if (string(argv[i])=="-v"){
            vehicle_name = string(argv[i+1]);
        } 
    }

    ofstream file_out;
    file_out.open ("state.csv");
    if(vehicle_name == "hovercraft"){
        int L, W;
        double start_x, start_y, goal_x, goal_y;
        infile >> L;
        infile >> W;
        infile >> start_x;
        infile >> start_y;
        infile >> goal_x;
        infile >> goal_y;

        hovercraft my_vehicle(L,W, start_x, start_y, goal_x, goal_y);
        hovercraft* vehicle = dynamic_cast<hovercraft*>(&my_vehicle);
    } else {
        cout<<"Invalid Vehicle: "<<vehicle_name<<"\n Exiting...\n";
        return 0;
    }

    vehicle->print_state(0);
}

这是对实际代码的简化,但我认为它抓住了问题。我想要的结果是 print 在 if 语句内部和之后的工作方式相同,但之后它总是打印 "no vehicle".

您在 if 语句的范围内重载了变量 rptr,这隐藏了在 main 顶部声明的变量。因此,您的最终 rptr->print() 是未定义的行为,因为您在未初始化的指针上调用虚函数。

简单去除重载如下:

robot *rptr = nullptr;

if (*argv[1] == 'h')       // <-- also fixed this (yours was broken)
{
    rptr = new hovercraft();
    rptr->print();
}
else if (*argv[1] == 'q')  // <-- also fixed this (yours was broken)
{
    rptr = new quadrotor();
    rptr->print();
}
else
{
    std::cout << "Invalid vehicle input" << std::endl;
}

if (rptr)
{
    rptr->print(); 
}

您可能还想考虑使用 std::shared_ptrstd::unique_ptr(以及 std::make_sharedstd::make_unique)来正确管理动态内存的生命周期。