如果我们没有虚拟构造函数,那么为什么我们有虚拟析构函数?构造函数也可以是虚拟的吗?
问问题
20906 次
3 回答
26
- 虚拟构造函数没有意义 - 您准确声明创建的类型,并且在编译时众所周知。编译器不需要[实际上也不需要,因为动态调度是基于仅在对象创建后才创建的信息]。所以没有虚拟构造函数。
- 虚拟析构函数对于防止内存泄漏和监控系统很重要。假设你有
A* a = new B;
[B
继承自A
],然后你delete a;
- 编译器无法知道a
是B
[在一般情况下],并且将调用A
' 的析构函数 - 如果它不是虚拟的,你可能会遇到内存泄漏,或其他故障。 - 使用虚拟析构函数 - 您确保
B
调用析构函数,因为B
正在销毁一个对象。
于 2012-03-29T10:59:22.827 回答
2
需要虚拟析构函数,因为在销毁时,您并不总是知道要处理的类型:
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;
}
delete
上面程序中的不main
知道它是p
指向 aBase
还是Derived
对象,但是如果Base
析构函数是virtual
(应该是),那么delete
可以使用*p
' vtable找到正确的析构函数。
相比之下,在构建时,您总是知道您正在创建什么样的对象。(如果你不知道,那么你可以创建一个知道的工厂或“虚拟构造函数”。)
于 2012-03-29T11:00:33.467 回答
0
#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)会调用基类的析构函数,但实际座右铭是删除派生类。因此我们需要析构函数本质上是虚拟的。
于 2017-04-29T06:59:22.197 回答