【发布时间】:2012-04-13 00:23:19
【问题描述】:
如果我们没有虚拟构造函数,那么为什么我们有虚拟析构函数?构造函数也可以是虚的吗?
【问题讨论】:
-
@TomaszNurkiewicz:我认为问题是,为什么我们在 C++ 中有虚拟析构函数?
标签: oop constructor virtual-destructor
如果我们没有虚拟构造函数,那么为什么我们有虚拟析构函数?构造函数也可以是虚的吗?
【问题讨论】:
标签: oop constructor virtual-destructor
A* a = new B; [B 继承
来自A],然后是delete a; - 编译器无法
知道a 是B [在一般情况下],并将调用A's
析构函数 - 如果它不是虚拟的,你可能会遇到内存泄漏,
或其他故障。B 的析构函数是
调用,因为 B 对象正在被销毁。【讨论】:
new MyClass;。创建对象的动态类型和静态类型——完全一样,是真正的具体对象。
需要虚拟析构函数,因为在销毁时,您并不总是知道要处理的类型:
Base *make_me_an_object()
{
if (the_moon_is_full())
return new Derived();
else
return new Base();
}
int main()
{
Base *p = make_me_an_object();
delete p;
}
上述程序的main 中的delete 不知道它的p 是指向Base 还是Derived 对象,但是如果Base 析构函数是virtual(因为它应该是),那么delete可以使用*p的vtable找到正确的析构函数。
相比之下,在构建时,您总是知道要创建什么样的对象。 (如果你不知道,那么你可以创建一个知道的工厂或“virtual constructor”。)
【讨论】:
#include<iostream>
using namespace std;
class base {
protected:
int a;
};
class derived : public base {
};
int main() {
base * pointer_of_base = new derived;
delete pointer_of_base; // this will delete the base calss not the derived
}
构造函数在我们创建类的对象时被调用一次,所以当我们继承基类时,构造函数只调用一次,所以不需要是虚拟的。
但是当我们从基类的指针访问派生类时,如果我们想删除派生类的对象,我们通过基类的指针删除它,但是delete(pointer_of_base)会调用基类的析构函数但实际的座右铭是删除派生类。因此我们需要析构函数本质上是虚拟的。
【讨论】: