构造函数和析构函数是否可以是虚函数,为什么?
1. 为什么构造函数不能为虚函数?
虚函数的调用需要虚函数表指针,而该指针存放在对象的内容空间中;若构造函数声明为虚函数,那么由于对象还未创建,还没有内存空间,更没有虚函数表地址用来调用虚函数——构造函数了。
2. 为什么析构函数可以为虚函数,如果不设为虚函数可能会存在什么问题?
首先析构函数可以为虚函数,而且当要使用基类指针或引用调用子类时,最好将基类的析构函数声明为虚函数,否则可以存在内存泄露的问题。
举例说明:
子类B继承自基类A;A *p = new B; delete p;
1) 此时,如果类A的析构函数不是虚函数,那么delete p;将会仅仅调用A的析构函数,只释放了B对象中的A部分,而派生出的新的部分未释放掉。
2) 如果类A的析构函数是虚函数,delete p; 将会先调用B的析构函数,再调用A的析构函数,释放B对象的所有空间。
补充: B *p = new B; delete p;时也是先调用B的析构函数,再调用A的析构函数。
#include <iostream>
using namespace std;
class A
{};
class B:public A
{};
class Base
{
public:
Base(void)
{
cout << "我是Base类的构造函数" << endl;
}
~Base(void)
{
cout << "我是Base类的析构函数" << endl;
}
virtual A* func(void)
{
cout << "我是Base类的虚函数" << endl;
}
};
class Test:public Base
{
public:
Test(void)
{
cout << "我是Test类的构造函数" << endl;
}
~Test(void)
{
cout << "我是Test类的析构函数" << endl;
}
//它可以覆盖负累中的虚函数
B* func(void)
{
cout << "我是Test类的函数func" << endl;
}
};
void test(Base* b)
{
b->func();
}
int main(int argc,const char* argv[])
{
Base* t = new Test;
cout << "----------" << endl;
test(t);
cout << "----------" << endl;
delete t;
//test(new Base);
}
上面可以说是多态的一种运用,用父类指针来指向子类对象,然后调用被覆盖函数。
输出:
当父类中的析构函数~Base(void)没有加virtual关键字时,在释放内存时只会调用父类的虚函数释放父类占用的内存,而子类Test的虚函数并没有被调用,这就会导致内存泄露,没有及时得到释放。
我是Base类的构造函数
我是Test类的构造函数
我是Test类的函数func
我是Base类的析构函数
此时的结果为父类中的析构函数~Base(void)加virtual关键字后,也调用了子类的虚函数。
我是Base类的构造函数
我是Test类的构造函数
我是Test类的函数func
我是Test类的析构函数
我是Base类的析构函数