You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法从存储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,提问作者Александр Тымин

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 06:53:09