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

C++ can you downcast class pointer conditionally?

本文关键字:转换 指针 有条件 C++      更新时间:2023-10-16

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

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

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);
}

这是从实际代码中简化的,但我认为它抓住了问题。我想要的结果是,打印在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(来正确管理动态内存的生存期。