为什么C++不能有虚构造函数,却可以有虚析构函数

来源:互联网 发布:细说php第四版 编辑:程序博客网 时间:2024/05/16 23:47
class B{ public :    virtualvoid m1();    virtualvoid m2(); }; class D : public B{     virtualvoid m1(); } 

一、C++的动态绑定使用vtable(虚成员函数表)来实现。vtable支持运行时查询,使系统可以将某一函数名绑定到vtable的特定入口地址。

例如上段代码的虚函数表为:

虚成员函数       入口地址      虚成员函数            入口地址B::m1          0x7723         D::m1                        0x99a7            //重定义的B::m2          0x23b4         D::m2                        0x23b4            //完全继承
  • 由于系统执行虚函数时,要从对象的vtable找到函数入口地址,而且vtable是存储于对象的内存空间中。假如对象没有实例化,就找不到vtable。因此,构造函数不能是vittual。

  • 但是,析构函数一般都需要加上virtual,假如定义Base *b = new Deriver; Deriver是Base的子类,并且~Base()不为virtual。那么当对象被注销时,系统只会调用~Base(),而不会调用~Deriver(),因为b是Base类型,已被静态绑定析构函数。如果基类或子类用new创建了内存空间,就必须通过析构函数销毁。因此必须使用vitual析构函数,实现动态绑定。

  • 另外:从另一个角度也可以看出构造函数不能为虚函数,1,虚函数的作用在于通过父类的指针或者引用调用它的时候能够变成调用子类的那个成员函数。而构造函数是在创建对象时自动调用的,不可能通过父类或者引用去调用,因此就规定构造函数不能是虚函数。

二、构造函数不需要是虚函数,也不允许是虚函数,因为创建一个对象时我们总是要明确指定对象的类型,尽管我们可能通过实验室的基类的指针或引用去访问它

但析构却不一定,我们往往通过基类的指针来销毁对象。这时候如果析构函数不是虚函数,就不能正确识别对象类型从而不能正确调用析构函数


#include <iostream>using namespace std;class A{public:    A()    {        cout << "A" << endl;    }    ~A()    {        cout << "~A" << endl;    }};class B:public A{public:    B()    {        cout << "B" << endl;    }    ~B()    {        cout << "~B" << endl;    }};class C:public B{public:    C()    {        cout << "C" << endl;    }    ~C()    {        cout << "~C" << endl;    }};int main(){    A *b = new B;    cout << endl;    A *c = new C;    cout << endl;    delete b;    cout << endl;    delete c;    return 0;}

这里写图片描述

析构函数加上 virtual 后:
这里写图片描述

0 0