C ++继承不在堆栈上工作?

时间:2012-02-08 21:32:46

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

这是一个大得多的代码的缩小问题。我知道C.a应该在堆上,但我想避免改变“。”到“ - >”代码中到处都是。有没有办法可以绕过这个bug? (编译器是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;
};

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

new (&a) AB();  // everything works here except virtuals

这不起作用:此处的行为未定义。 aAA类型的对象。您无法在其位置构造类型为AB的对象。您可以构造的唯一对象是AA对象。

如果需要a的多态行为,则应使用指向动态分配对象的指针。优选地,指向动态分配的对象的智能指针,例如std::unique_ptr<AA>。另请注意,AA应该有一个虚拟析构函数。