1、什么时候需要virtual析构函数?
polymorphic(带多态性质的)base class应该声明一个virtual析构函数。就是说,如果class带有任何virtual函数,它就应该有一个virtual析构函数。
#include <cstdio>
#include <cstring>
class Base
{
public:
Base(const char *s)
{
if(s)
{
int len = strlen(s);
m_base_name = new char[len+1];
strcpy(m_base_name, s);
}
}
~Base()//
{
printf("Base destruct\n");
if(m_base_name)
{
delete [] m_base_name;
}
}
private:
char *m_base_name;
};
class Derived : public Base
{
public:
Derived(const char *s1, const char *s2):Base(s1)
{
if(s2)
{
int len = strlen(s2);
m_derived_name = new char[len+1];
strcpy(m_derived_name, s2);
}
}
~Derived()
{
printf("Derived destruct\n");
if(m_derived_name)
{
delete [] m_derived_name;
}
}
private:
char *m_derived_name;
};
int main(int argc, char **argv)
{
Base *p = new Derived("base name", "derived name");
delete p;
return 0;
}
执行结果是:Base destruct
new出来的Derived对象仅基类成分被销毁了。c++明白指出,当derived class对象经由一个base class指针删除,而该base class带着一个non-virtual析构函数,其结果未定义。反之,如果此处将Base类的析构函数声明为虚函数,当执行“delete p;” 时,就能根据p所指对象的虚函数表找到正确的析构函数版本。将析构函数声明为虚函数,与将一般的函数声明为虚函数有一点不同,那就是基类中虚函数名字和派生类的虚函数名字不相同,这是虚函数的一种特殊情形。
2、什么时候不需要virtual析构函数?
classes的设计目的不是为了具备多态性(polymorphically),就不该声明virtual析构函数。
(1) virtual函数会导致对象体积的增大(用于存放virtual table pointer)。
(2) virtual table pointer的存在,导致class的结构与其他语言(如C语言)内的相同声明的结构不一样,因此可移植性变弱了。
例如:
//c++
class Point
{
public:
Point(int x, int y);
~Point();
private:
int m_x;
int m_y;
};
//c
struct Point
{
int x;
int y;
};
以上声明有相同的内存结构。但是class Point里面如果有虚函数,那么它们的结构就不相同了。
3、延伸:classes的设计目的不是为了具备多态性(polymorphically)时,使用它们时需要注意的问题。
class SpecialString : public std::string
{
...
};
SpecialString *pss = new SpecialString("Impending Doom");
std::string *ps;
...
ps = pss;
...
delete ps; //未定义
相同的分析适用于任何不带virtual析构函数的class,包括所有的STL容器,如vector,list,set等等。