virtual的应用实现了多态,那么对于类中的两个特殊的函数,构造函数和析构函数能不能用虚函数?
(1)构造函数不能设计为虚函数
如果类中定义了虚函数,则会生成虚表,那么为了调用这个虚函数就要通过虚表来调用。可是,构造函数比较特殊,构造函数是在对象完全构造之前运行,那么就导致对象还没有实例化,那就还没有内存空间,没有内存空间肯定就找不到虚表,找不到虚表就不能调用虚函数,所以构造函数不能是虚函数。
(2)用来做基类的析构函数设计为虚函数
为什么这么说呢?不做基类的析构函数也可以设计为基类,但是没有意义,而且这样做编译器会给类中加虚函数表里面存放虚函数指针,这样增加的类空间的大小,所以只有用来做基类的析构函数设计为虚函数较合理。
为什么基类的析构函数设计为虚函数,看如下的例子:
#include <iostream>
#include <new>
using namespace std;
class A{
public:
A(){};
virtual ~A(){cout<<"A::~A()"<<endl;}
virtual void func1(){cout<<"A::func1()"<<endl;}
};
class B : public A{
public:
B(){};
~B(){cout<<"B::~B()"<<endl;}
void func1(){cout<<"B::func1()"<<endl;}
};
int main()
{
A *p = (A *)new B;
p->func1();
delete p;
return 0;
}
编译结果如下:
B::func1()
B::~B()
A::~A()
可以看出用基类指针p指向一个生成的派生类B的对象,在delete p释放基类指针时,会同时释放派生类B所占用的内存空间。这正是我们想要的。
但是如果将程序中的基类A的析构函数改为非虚函数,则编译结果为:
B::func1()
A::~A()
可以看出并没有释放基类指针指向的空间的资源,二仅仅是释放了指针,这样会造成内存泄露。