首先我们需要知道为什么基类的析构函数是虚函数:
因为在实现多态时候,当基类操作派生类,在析构时防止只析构基类而不析构派生类的状况发生从而造成内存泄露之类的问题。
在这一段的解释中,我们的关注点应该在
1.基类操作派生类
2.只析构基类
下面有几个例子
<span style="font-size:14px;">#include <iostream>
using namspace std;
class Base{
Base() {};
~Base(){cout<<"output form destructor of class Base"<<endl};
void DoSomething() { cout << "Do something in class Base!" << endl; };
}
class Dervied:public Base{
Dervied() {};
~Dervied() {cout<<"output form destructor of class Derviced"<<endl;};
void DoSomething() { cout << "Do something in class Derviced!" << endl; };
}
int main(){
Derived *p = new Derived;
p->DoSomething();
delete p;
return 0;
}</span>
<span style="font-size:14px;">运行结果:</span>
<span style="font-size:14px;"></span>
Do something in class Derviced!
Output from the destructor of class Derviced!
Output from the destructor of class Base!
b.第二段代码
<span style="font-size:14px;">#include<iostream>
using namespace std;
class ClxBase{
public:
ClxBase() {};
~ClxBase() {cout << "Output from the destructor of class ClxBase!" << endl;};
void DoSomething() { cout << "Do something in class ClxBase!" << endl; };
};
class ClxDerived : public ClxBase{
public:
ClxDerived() {};
~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };
void DoSomething() { cout << "Do something in class ClxDerived!" << endl; }
};
int main(){
ClxBase *p = new ClxDerived;
p->DoSomething();
delete p;
return 0;
}
</span>
<span style="font-size:14px;">运行结果:</span><span style="font-family: Tahoma; background-color: rgb(255, 255, 255);">:</span>
Do something in class ClxBase!
Output from the destructor of class ClxBase!
这段代码中基类的析构函数同样不是虚函数,不同的是在main函数中用基类的指针去操作继承类的成员,释放指针P的过程是:只是释放了基类的资源,而没有调用继承类的析构函数.调用 dosomething()函数执行的也是基类定义的函数.
一般情况下,这样的删除只能够删除基类对象,而不能删除子类对象,形成了删除一半形象,造成内存泄漏.
在公有继承中,基类对派生类及其对象的操作,只能影响到那些从基类继承下来的成员.如果想要用基类对非继承成员进行操作,则要把基类的这个函数定义为虚函数.
析构函数自然也应该如此:如果它想析构子类中的重新定义或新的成员及对象,当然也应该声明为虚的.
c.第三段代码:
<span style="font-size:14px;">#include<iostream>
using namespace std;
class ClxBase{
public:
ClxBase() {};
virtual ~ClxBase() {cout << "Output from the destructor of class ClxBase!" << endl;};
virtual void DoSomething() { cout << "Do something in class ClxBase!" << endl; };
};
class ClxDerived : public ClxBase{
public:
ClxDerived() {};
~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };
void DoSomething() { cout << "Do something in class ClxDerived!" << endl; };
};
int main(){
ClxBase *p = new ClxDerived;
p->DoSomething();
delete p;
return 0;
}
</span>
<span style="font-size:14px;">运行结果:</span><span style="font-family: Tahoma; background-color: rgb(255, 255, 255);">:</span>
Do something in class ClxDerived!
Output from the destructor of class ClxDerived!
Output from the destructor of class ClxBase!
这段代码中基类的析构函数被定义为虚函数,在main函数中用基类的指针去操作继承类的成员,释放指针P的过程是:只是释放了继承类的资源,再调用基类的析构函数.调用dosomething()函数执行的也是继承类定义的函数.
如果不需要基类对派生类及对象进行操作,则不能定义虚函数,因为这样会增加内存开销.当类里面有定义虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间.所以,只有当一个类被用来作为基类的时候,才把析构函数写成虚函数.