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

问题描述:

这是一个更大代码的缩小问题。我知道C.a应该在堆上,但我想避免改变“。”到代码中的“ - >”无处不在。有没有办法绕过这个bug? (编译为g ++ 4.6.1) 我认为这是因为C++允许它,但不恰当的行为的错误...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; 
}; 
+0

如果你的愿望只是使用。而不是 - >为什么不只是使用参考?在堆上创建对象,然后在想要使用它时,只需将其分配给本地引用即可。 – Nerdtron 2012-02-08 21:34:22

+0

Nerdtron,这不适用于课堂。 AA * _a; AA&a = * _a; 现在_a需要是const。 – chhu79 2012-02-08 21:59:54

+0

@ chuu79:为什么不行?是的,'_a'不能指向不同的内存位置,但可以在该位置创建一个新对象。另一方面,改变类型仍然是非法的。刚刚回答了上周的一个问题。 – 2012-02-08 22:06:30

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

该标准不需要诊断,编译器不负责确保你不做任何愚蠢的事情。

+1

嗯太糟糕了!有种悲伤的说,编译器无法阻止对堆栈指针的写入访问... – chhu79 2012-02-08 21:49:36

+1

@ chuu79:什么是堆栈指针?为什么要访问堆栈被阻止?你有一种非常不寻常的(和错误的)思考方式。 – 2012-02-08 22:07:16

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

这实际上并不奏效:这里的行为是未定义的。 aAA类型的对象。你不能在它的位置构造一个AB类型的对象。您允许构建的唯一对象是AA对象。

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