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;
};
唯一的错误是在你的代码。您正在调用未定义的行为(实际上有几种不同的方式)。
该标准不需要诊断,编译器不负责确保你不做任何愚蠢的事情。
嗯太糟糕了!有种悲伤的说,编译器无法阻止对堆栈指针的写入访问... – chhu79 2012-02-08 21:49:36
@ chuu79:什么是堆栈指针?为什么要访问堆栈被阻止?你有一种非常不寻常的(和错误的)思考方式。 – 2012-02-08 22:07:16
new (&a) AB(); // everything works here except virtuals
这实际上并不奏效:这里的行为是未定义的。 a
是AA
类型的对象。你不能在它的位置构造一个AB
类型的对象。您允许构建的唯一对象是AA
对象。
如果您需要a
的多态行为,则应该使用指向动态分配对象的指针。优选地,指向动态分配的对象的智能指针,例如std::unique_ptr<AA>
。还请注意AA
应该有一个虚拟析构函数。
如果你的愿望只是使用。而不是 - >为什么不只是使用参考?在堆上创建对象,然后在想要使用它时,只需将其分配给本地引用即可。 – Nerdtron 2012-02-08 21:34:22
Nerdtron,这不适用于课堂。 AA * _a; AA&a = * _a; 现在_a需要是const。 – chhu79 2012-02-08 21:59:54
@ chuu79:为什么不行?是的,'_a'不能指向不同的内存位置,但可以在该位置创建一个新对象。另一方面,改变类型仍然是非法的。刚刚回答了上周的一个问题。 – 2012-02-08 22:06:30