Crashed when i delete a c++ object
Possible Duplicate:
When to use virtual destructors?
[第二个迪西]嗨,伙计们!你们都在谈论虚拟析构函数。我还想到了基类的析构函数。但另一个考验是:甲类{公众:(){}虚拟虚空乐趣(){}私人:int;};
当A类有一个虚拟函数(而不是虚拟去流通器)时,没关系。删除ptra没问题!
所以,我认为a只需要一个vptr来激活多态性。非类as
destructor must be virtual.
Class A的析构函数不是虚拟的,只是可以使资源不被释放。正确地。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| class A
{
public:
A()
{
}
/*virtual*/ ~A()
{
}
private:
int mIntA;
};
class B : public A
{
public:
B()
{
mIntB = 1234;
}
virtual ~B()
{
int i = 0;
}
private:
int mIntB;
}; |
我有一个A类和一个从A派生的B类;a没有任何虚拟函数。所以当我这样做的时候:
1 2
| A* ptrA = new B;
delete ptrA; |
它崩溃了!
但是当给A加上一个虚拟的乐趣时,没关系。如我们所知,ptra是一个b对象。但是为什么呢?
- stackoverflow.com/questions/461203/…
- 因为未定义的行为意味着任何事情都可能发生。
- 基本上,您不了解虚拟析构函数以及为什么需要在基类中使用它们。人们称之为完全复制品的问题并不完全正确。但所有的答案都会回答你的问题。
您有一个非虚拟析构函数!
(这意味着当调用析构函数时,调用的是a的析构函数,而不是b的,即使对象被分配为b)
- 因为操作调用了未定义的行为,恶魔飞出了操作鼻子。-每个人2.com/title/demons+fly+out+your+nose或en.wikipedia.org/wiki/…
- "哦,嗯?"这到底有什么未定义的?
- @让我在派生类的对象上调用基类的析构函数。请参见这里的项目20.7:PARASIFIFT COM/C++-FAQLIT/ValueStudio.HTML
- @对于没有虚拟析构函数的多态类来说,这是正确的。在这种情况下,您实际上是为类A的对象调用类A的析构函数。唯一的事情是这个对象驻留在一个更大的内存块中。
- @让我来-不,在所有情况下都是未定义的。delete不是free的等价物。编译器没有理由在C++中存储分配的块的大小,不管怎样,对于派生类内部的基类实例的指针可能由于任何原因而不能指向块的开头。
- @是的,这是因为delete试图取消分配一个无效的指针,但定义得很好。指向基类的指针必须指向基类的开头,特别是当基类不是多态的时候。
- @让我来-删除一个无效的指针定义不好。唯一无效的指针是空指针,当您删除它时,它是为其定义的。是的,指向基类的指针必须指向基类的开头,但它不必指向它所属的派生类的开头。给出一个明显的例子…您可以拥有多个继承,而不需要您知道的虚拟函数。
- @让我来:取消分配一个无效指针是定义良好的?!
- @首先,当您尝试解除分配一个无效指针时将发生的事情不是未定义的,而是定义了实现。我说的是这样一个事实,即将发生的是一个无效指针的释放,而这将发生的定义很好。
- 这到底是什么意思?
- @假设类B是从类A派生出来的。那么,B b; A &a = b; if (reinterpret_cast(&a) != reinterpret_cast(&b)) { ::std::cerr <<"Yay!
"; }可以打印出Yay!或者不打印出来。它不确定是否存在。它不是实现定义的,比如char是否是有符号类型,它是未定义的,比如访问数组的边界。
- @Omni-Try static_cast。本案不涉及reinterpreted_cast。
- @让我来吧-我放弃了。当我给你一个答案时,你要我编辑它直到它出错。
- @Omni B b; A* a = &b;定义明确。相当于A* a = static_cast(&b);。它将指针返回到B内部的a。是的,如果在B内部的a实例之前没有偏移量,那么指针可能是相同的。但是没有不明确的行为。一切都有很好的定义。以及调用的析构函数。
- @让我来吧-你错了。class A { int joe; }; class AA { char fred; }; class AAA { float barney; }; class B : public AA, public A, public AAA { };。如果声明看起来像这样,如何在代码中定义调用delete a;?
- @好吧,随便你想要什么。我不会把我说过的话都转寄出去。
- @让我来-我为此创建了一个stackoverflow问题:stackoverflow.com/questions/4178889/&hellip;-我想看看你是否真的可以承认犯了任何错误。
- 嗨,伙计们!你们都在谈论虚拟析构函数。另外,我认为基本类cx1〔0〕是可以的。删除ptra没问题!所以,我认为a只需要一个vptr来激活多态性。不是类as destructor must be virtual. Class A的析构函数不是虚拟的,只会使资源不能正确释放。
A类不是多态的,因此删除不可能知道ptrA实际上指向一个分配的块,因此释放崩溃。