为什么析构函数要为虚函数
1.不管基类的析构函数是否为虚构函数,子类在销毁时,都会调用基类的虚构函数
2.举例说明
虚函数的作用就是通过基类指针或者是基类引用来调用合适的子类函数。
假设有如下的继承关系Descendant–>Derive–>Base,它们中都定义了sing()的函数
代码块
类的定义,例如:
class Base
{
public:
Base(){cout<<"Base construct..."<<endl;}
~Base(){cout<<"Base destruct..."<<endl;}
virtual void sing(){cout<<"Base singing..."<<endl;}
};
class Derive : public Base
{
public:
Derive(){cout<<"Derive construct..."<<endl;}
~Derive(){cout<<"Derive destruct..."<<endl;}
virtual void sing(){cout<<"Derive singing..."<<endl;}
};
class descendant : public Derive
{
public:
descendant(){cout<<"descendant construct..."<<endl;}
~descendant(){cout<<"descendant destruct..."<<endl;}
void sing(){ cout<<"descendant singing..."<<endl;}
};
实例1
Derive *derivePtr = new descendant();
derivePtr->sing();
delete derivePtr;
修改
在析构函数前面加上virtual标签,则子类销毁时,会调用其析构函数
原理分析
更详细地解释是 virtual告诉编译器应该使用 静态联编 还是 动态联编
无virtual,编译器采用 静态联编
将源代码中的函数调用解释为执行特定的函数代码被称为函数名联编(binding).
在编译过程中进行联编被称为静态联编(static binding),又称早期联编(early binding).它对函数的选择是根据基于对象的 指针或者引用来确定的。(即指针或者引用 指向哪个对象就调用哪个对象的相应的函数)
编译器必须生成能够在程序运行时选择正确的虚方法的代码,这被称为动态联编(dynamic binding), 又称为晚期联编(late binding)
为什么有两种类型的联编以及为什么默认为静态联编?
1.为使程序能够在运行阶段进行决策,必须采取一些方法来跟踪实际运行中基类指针或引用指向的对象类型,这增加了额外的开销.
2.如果类不会用作基类,则不需要动态联编;
3.如果派生类不重新定义基类的任何方法,也不需要使用动态联编;