【问题标题】:C++ inheritance not working on stack?C ++继承不适用于堆栈?
【发布时间】:2012-03-01 09:18:16
【问题描述】:

这是一个大得多的代码的缩小问题。我知道 C.a 应该在堆上,但我想避免更改“。”在代码中的任何地方都使用“->”。有没有办法可以绕过这个错误? (编译器为 g++ 4.6.1) 我认为这是一个错误,因为 c++ 允许它但行为不正确......

#include <iostream>
using namespace std;

class AA {
public:
    virtual void foo() {
        cout << "AA!\n";
    };
};

class AB : public AA {
public:
    AB() : AA() { cout << "construct AB!\n"; }

    void foo() {
        cout << "AB!\n";
    }
};

class C {
public:
    AA a;
    void xchg() {
        a.~AA();
        new (&a) AB();  // everything works here except virtuals
    }
};

int main() {
    C c;
    c.a.foo(); // -> AA
    c.xchg();
    c.a.foo(); // -> AA :(

    AA *aa = new AB();
    aa->foo(); // -> AB (virtual works)

    return 0;
};

【问题讨论】:

  • 如果您只想使用 .而不是 -> 为什么不只使用参考?在堆上创建对象,然后当您想使用它时,只需将其分配给本地引用。
  • Nerdtron,这在课堂上是行不通的。 AA *_a;AA &a = *_a;现在 _a 需要为 const。
  • @chuu79: 为什么这行不通?是的,_a 不能指向不同的内存位置,但可以在该位置创建一个新对象。另一方面,改变类型仍然是非法的。上周刚刚回答了一个关于该问题的问题。
  • 哇,谢谢,这实际上可以解决我的问题!

标签: c++ inheritance stack virtual new-operator


【解决方案1】:

唯一的错误在于您的代码。您正在调用未定义的行为(实际上以几种不同的方式)。

标准不需要对此进行诊断,确保您不会做任何愚蠢的事情不是编译器的责任。

【讨论】:

  • 嗯,太糟糕了!有点遗憾的是编译器无法阻止对堆栈指针的写访问......
  • @chuu79: 什么堆栈指针?为什么要阻止对堆栈的访问?你有一种非常不寻常(和错误)的思考方式。
【解决方案2】:
new (&a) AB();  // everything works here except virtuals

这实际上不起作用:这里的行为是未定义的。 aAA 类型的对象。您不能在其位置构造 AB 类型的对象。唯一允许您构造的对象是 AA 对象。

如果您需要a 的多态行为,您应该使用指向动态分配对象的指针。最好是指向动态分配对象的智能指针,例如std::unique_ptr&lt;AA&gt;。另请注意,AA 应该有一个虚拟析构函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-11
    • 2017-01-24
    • 2016-06-28
    • 2021-02-27
    • 1970-01-01
    相关资源
    最近更新 更多