无法从存储Wall子类对象的栈中访问栈顶元素字段
问题分析与解决方案
你遇到的核心问题是子类重定义父类成员变量导致的隐藏问题,加上类型判断逻辑失效,使得访问栈顶对象成员时出现未定义行为(异常/垃圾值)。下面逐一拆解并给出修复方案:
1. 核心问题拆解
成员变量隐藏
你的Disk和Сylinder子类重新定义了父类Wall中的radiusInside、radiusOutside、Height等成员变量,比如:
// 父类Wall double radiusInside; double radiusOutside; double Height; // 子类Disk double radiusInside; // 重新定义,直接隐藏父类同名成员 double radiusOutside;
当你通过Wall*(栈中存储的是父类指针)访问这些成员时,实际读取的是父类未初始化的成员变量,而非子类中赋值的数值,这直接导致垃圾值或内存访问异常。
类型判断逻辑失效
子类中注释掉了自己的name定义,所有对象都使用父类的name = "Wall",导致你通过name判断对象类型的代码完全不起作用。
修复方案
方案一:删除子类重复定义的成员变量
子类无需重新定义父类已有的成员,直接使用继承的变量即可:
// 修改后的Disk类 class Disk : public Wall { public: Disk(double radiusOutside, double radiusInside); ~Disk(); QString name = "Disk"; // 启用子类专属name,覆盖父类值 int index; }; // 修改后的Сylinder类 class Сylinder : public Wall { public: Сylinder(double radiusOutside, double height); ~Сylinder(); QString name = "Cylinder"; // 启用子类专属name int index; };
同时在子类构造函数中直接初始化父类成员:
// Disk构造函数示例 Disk::Disk(double radiusOutside, double radiusInside) { this->radiusOutside = radiusOutside; this->radiusInside = radiusInside; } // Сylinder构造函数示例 Сylinder::Сylinder(double radiusOutside, double height) { this->radiusOutside = radiusOutside; this->Height = height; }
方案二:用多态实现类型判断(更优雅)
如果需要灵活扩展类型行为,建议用虚函数替代直接访问name字段:
// 修改Wall类,添加虚函数返回类型名 class Wall: public QObject { Q_OBJECT public: double radiusInside; double radiusOutside; double Height; static int indexNumber; static double coordinateZ; Wall(); virtual ~Wall(); // 虚函数返回类型名 virtual QString getTypeName() const { return "Wall"; } friend double GeneratorMonteCarlo(); }; // Disk类重写虚函数 class Disk : public Wall { public: Disk(double radiusOutside, double radiusInside); ~Disk(); int index; QString getTypeName() const override { return "Disk"; } }; // Сylinder类重写虚函数 class Сylinder : public Wall { public: Сylinder(double radiusOutside, double height); ~Сylinder(); int index; QString getTypeName() const override { return "Cylinder"; } };
然后在判断逻辑中调用虚函数:
QString name = stack.top()->getTypeName(); if (name == "Cylinder") { if ((selected_text == "Cylinder" && val1 == stack.top()->radiusOutside) || (selected_text == "Disk" && val1 == stack.top()->radiusOutside) || (selected_text == "Disk" && val2 == stack.top()->radiusInside)) { return true; } }
方案三:确认栈的模板参数正确
确保你的Stack实例化时使用Wall类型,这样才能统一存储所有子类对象:
Stack<Wall> stack; // 正确:存储Wall*,可指向任意子类对象
额外注意事项
- 给
Wall的构造函数添加默认初始化,避免父类成员未初始化:Wall::Wall() : radiusInside(0), radiusOutside(0), Height(0) {} - 检查
push到栈中的对象是否用new创建,避免栈内存对象销毁后指针悬空(这也是触发异常的常见原因)。
内容的提问来源于stack exchange,提问作者Александр Тымин
相关产品推荐
相关产品推荐

