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_ptr
或 std::unique_ptr
(以及 std::make_shared
或 std::make_unique
)来正确管理动态内存的生命周期。
我有一个基础 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_ptr
或 std::unique_ptr
(以及 std::make_shared
或 std::make_unique
)来正确管理动态内存的生命周期。