关于virtual destructor的有关问题

关于virtual destructor的问题?
请问:
为什么要把析构函数定义成虚函数?


------解决方案--------------------
大家说的很详细,我补充一点:
也不是只要类被继承,就要定义虚析构。。。
确切的说是避免在使用基类指针指向一个子类对象的时候,漏掉子类析构函数的调用

class A
{
A(){};
~A(){cout < < "Base destructor " < <endl;};
};
class B: public A
{
B(){};
~B(){cout < < "derived destructor " < <endl;};
};

//call Fn
int call()
{
A *p = new B();
...
delete p;
return 0;
}

你可以验证一下,结果肯定是只有“Base destructor”
如果你在~A(){}前面加了virtual,就会显示
derived destructor
Base destructor

所以这种情况下需要虚析构。。
不过为了安全,也可以在基类定义中都使用虚析构,依个人习惯吧
------解决方案--------------------
#pragma pack(x)
#pragma pack(2)
struct test1
{
char a;
char b;
 int c;
}
sizeof(test1) = 6;
∴ 按min(结构体中最大的成员长度,x)来对齐的。
------解决方案--------------------
先解释对齐问题
VC 和GCC 的对齐方式做过优化。
默认情况下,其对齐方式是按照结构体里面最大结构体长度进行对齐。
怎么说呢?
比如一个结构体里面全部都是char型,则其对齐方式为1字节对齐,所以
struct test1
{
char a;
char b;
}//大小为2
struct test1
{
char a;
char b;
}//大小为3

比如一个结构体里面全部最大的是unsigned short型,则其对齐方式为2字节对齐
typedef struct
{
char a;
unsigned short b;
char c;
}struct2; //大小为6

同理,如果里面有long 形,则按四字节对齐。
typedef struct
{
char a;
long b;
char c;
}struct2; //大小为12

这个规律算是一个总结规律,暂未发现其他地方有这样的论述,但是解释VC的对齐非常有效。
GCC 和 NEC 的一个编译器也是使用的上面方式。

对齐方式的原则当初写了三页的文档,这里稍微论述一下,学习对齐的主要作用还是优化数据结构的安排 ,比如
typedef struct
{
char a;
long b;
char c;
}struct1; //大小为12
而如下定义
typedef struct
{
char a;
char c;
short b;
}struct2; //大小为4
效果不大,但是容量减为原来的1/3



------解决方案--------------------
至于析构函数为定义成虚函数?

这个问题嘛,如果你不想其他类继承你这个类,你可以不写成虚函数
反过来说,如果看到一个类,其析构函数不是虚拟的,则意味着这个类不需要你去继承他。

原因如下:
基类的析构函数如果不是virtual 的会导致基类无法析构,导致可能的内存泄露。
此外还有更严重的问题:
如果基类没有虚函数,其则不会产vfptr,此时如果派生有虚函数,
则派生类会产生vfptr,这样会导致赋值异常.
严重是程序会立即崩溃。

这里不详细说了,以前专门研究过虚表,发个链接
http://blog.csdn.net/vlient/archive/2007/06/10/1647283.aspx