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

标签 c++ inheritance downcast

我有一个基类(机器人),根据传递给程序的参数,我想将机器人指针向下转换为特定的派生类。机器人类具有在每个派生类中定义的虚拟函数。

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

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 语句内及其之后的工作方式相同,但在它之后将始终打印“无车辆”。

最佳答案

您在 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_shared >std::make_unique) 来正确管理动态内存的生命周期。

关于C++ 可以有条件地向下转换类指针吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58618772/

相关文章:

c++ - 基于类实例的自动方法选择

java - 编译时和运行时的向下转换/向上转换错误?

c# - 是否可以避免沮丧?

C++ 将 DNS 条目添加到网络适配器中

c++ - c++ 中的 cout<<cout 和 cout<<&cout 有什么区别?

generics - 可空类型的类型层次结构中的位置是什么?

java - Hibernate 继承查询(条件)

c++ - 在 C++ OpenGL 程序中找出显卡驱动程序的名称

c++ - 获取一个新元组,其中包含元组中除第一个元素以外的所有元素

java - 如何模拟和验证在子类中调用的 ScheduledExecutorService 方法