向上转型后抽象父类指针无法获取子类属性及正确调用方法
问题原因与解决:父类指针无法获取子类成员变量值
问题核心
你遇到的问题是成员变量没有多态特性:子类slack中重新声明的type并不是对父类operation中type的重写,而是直接隐藏了父类的同名成员。当通过父类指针operation* op访问type时,编译器只会解析到父类中定义的type(值为-1),不会像虚函数那样动态绑定到子类的成员。而虚函数能正常工作,是因为它们依赖C++的虚函数表(vtable)实现了动态多态。
解决方案
方案1:复用父类的type成员(推荐)
取消子类中对type的重新声明,改为在子类构造函数中初始化从父类继承来的type:
修改父类,确保type可以被子类初始化:
class operation { public: ll time, bot; ll type; // 父类构造函数初始化默认值 operation() : type(-1) {} virtual void negate() = 0; virtual void print() = 0; virtual void execute() = 0; };
修改子类,在构造函数中赋值父类的type:
class slack:public operation{ public: slack() { type = op::slack; // 直接修改继承的父类成员 } // 其余虚函数实现不变 virtual void print() override {if(nExec == k) exit(0);cout << "Robot " << bot << " slacks off." << endl;} virtual void negate() override {} virtual void execute() override { if(nExec == k) exit(0); nExec++; } };
方案2:添加虚函数获取type
如果希望通过多态方式获取type,可以在父类中定义一个虚函数来返回type,子类可按需重写:
class operation { public: ll time, bot; ll type = -1; virtual void negate() = 0; virtual void print() = 0; virtual void execute() = 0; // 虚函数返回type virtual ll getType() const { return type; } }; class slack:public operation{ public: ll type = op::slack; // 重写getType返回子类的type virtual ll getType() const override { return type; } // 其余虚函数实现不变 };
此时通过op->getType()就能获取子类的type值。
方案3:强制向下转型(不推荐)
如果必须保留子类的type成员,可以将父类指针强制转换为子类指针后访问,但这种方式破坏了多态的封装性,仅在确定指针指向子类对象时使用:
cout << static_cast<slack*>(op)->type << endl;
修改后的完整代码(方案1)
#include <iostream> #include <vector> #include <deque> using std::string, std::cin, std::cout, std::vector, std::deque, std::endl; typedef long long ll; ll n, m, k, nExec; namespace op { const ll slack = 0, move = 1, swap = 2, mirror = 3, replace = 4, activate = 5, trigger = 6; } class operation { public: ll time, bot; ll type; operation() : type(-1) {} virtual void negate() = 0; virtual void print() = 0; virtual void execute() = 0; }; class slack:public operation{ public: slack() { type = op::slack; } virtual void print() override { if(nExec == k) exit(0); cout << "Robot " << bot << " slacks off." << endl; } virtual void negate() override {} virtual void execute() override { if(nExec == k) exit(0); nExec++; } }; int main() { k = 998244353; operation* op = new slack; cout << op->type << endl; // 输出0 op->print(); return 0; }
运行后输出:
0 Robot 0 slacks off.
内容的提问来源于stack exchange,提问作者openwld
相关产品推荐
相关产品推荐

