虚函数之析构函数和构造函数

来源:互联网 发布:钣金展开软件下载 编辑:程序博客网 时间:2024/05/21 06:33

        构造函数不能声明为虚函数,析构函数可以声明为虚函数,而且有时是必须声明为虚函数。
      不建议在构造函数和析构函数里面调用虚函数。

        1. 析构函数

        大家都知道,当我们delete一个动态分配的对象的指针时将执行析构函数,如果该指针指向继承体系中的某个类型,则有可能出现指针的静态类型与被删除对象的动态类型不符的情况,这种情况下,编译器就必须清楚它应该执行哪个版本的析构函数。

        我们通过在基类中将析构函数定义成虚函数以确保执行正确的析构函数版本。

        如果基类的析构函数不是虚函数,则delete一个指向派生类对象的基类指针将产生未定义的行为。

        2. 构造函数

        构造函数不能声明为虚函数,主要有以下原因:

                a.从存储空间角度

                虚函数对应一个vtable,这大家都知道,可是这个vtable其实是存储在对象的内存空间的。问题出来了,如果构造函数是虚的,就需要通过 vtable来调用,可是对象还没有实例化,也就是内存空间还没有,无法找到vtable,所以构造函数不能是虚函数。

                b.从使用角度

                虚函数的作用在于通过父类的指针或者引用来调用它的时候能够变成调用子类的那个成员函数。而构造函数是在创建对象时自动调用的,不可能通过父类的指针或者引用去调用,因此也就规定构造函数不能是虚函数。

                c.从实现角度

                vbtl在所有构造函数被调用后才建立,因而构造函数不可能成为虚函数。

Notes:

1. 在构造函数不要调用虚函数。在基类构造的时候,虚函数是非虚,不会走到派生类中,既是采用的静态绑定。显然的是:当我们构造一个子类的对象时,先调用基类的构造函数,构造子类中基类部分,子类还没有构造,还没有初始化,如果在基类的构造中调用虚函数,如果可以的话就是调用一个还没有被初始化的对象,那是很危险的,所以C++中是不可以在构造父类对象部分的时候调用子类的虚函数实现。但是不是说你不可以那么写程序,你这么写,编译器也不会报错。只是你如果这么写的话编译器不会给你调用子类的实现,而是还是调用基类的实现

2. 在析构函数中也不要调用虚函数。在析构的时候会首先调用子类的析构函数,析构掉对象中的子类部分,然后在调用基类的析构函数析构基类部分,如果在基类的析构函数里面调用虚函数,会导致其调用已经析构了的子类对象里面的函数,这是非常危险的。

原创粉丝点击