C++如何在构造函数和析构函数中调用虚拟函数
作者:lk_HIT
C++构造函数和析构函数中调用虚拟函数
C++构造器可以为虚拟函数吗?
不行。
因为构造器调用的时候会设置当前类的虚表地址,然后如果构造函数本身为虚拟函数,那么调用构造函数就需要提前访问虚表,此时虚表指针还没有指向虚表,就没法访问虚表。
构造函数中可以调用虚拟函数吗?
可以。
但是调用虚拟函数就是调用跟调用普通函数效果一样。
因为子类在创建的时候是先调用父类的构造器,父类的构造器先设置好父类的虚表地址,然后再执行构造器中的代码,然后在回到子类构造器,先将虚表地址替换为子类的虚表地址,然后执行子类构造器的代码。
因此如果在父类构造器中调用虚函数,那么此时是从父类的虚表中查找函数地址,查找到的还是父类的虚函数地址。因此会调用父类的虚函数,而不会调用子类的虚函数。
析构函数中可以调用虚拟函数吗?
可以。
但是调用虚拟函数跟调用普通函数没啥区别。
因为析构的时候先执行子类的析构函数,再执行父类的析构函数,在执行当前类的析构函数的时候会先将虚表地址设置为当前类的虚表地址,然后再从虚表里查找函数地址,因此找到的只能是当前的虚函数的地址。
父类的析构函数为什么要为虚函数?
因为如果父类析构函数不为虚函数,那么当对象析构的时候只会调用指针当前类型的析构函数,不会调用父类或者子类的析构函数,会导致资源泄漏。
如果父类的析构函数为虚函数,那么子类的析构函数在析构的时候会先调用子类的析构函数,再调用父类的析构函数。这样子就不会存在资源泄漏。
注:
(1)将子类和父类构造器和析构器调用串起来是编译器实现的
(2)子类和父类都有自己的虚表。子类或者父类的构造器和析构器在最开始都是将虚表设置为当前类的虚表。然后才真正调用构造函数和析构函数里的代码。
C++构造函数和析构函数的调用顺序
1、构造函数的调用顺序
基类构造函数、对象成员构造函数、派生类本身的构造函数
2、析构函数的调用顺序
派生类本身的析构函数、对象成员析构函数、基类析构函数(与构造顺序正好相反)
3、特例
- 局部对象,在退出程序块时析构
- 静态对象,在定义所在文件结束时析构
- 全局对象,在程序结束时析构
- 继承对象,先析构派生类,再析构父类
- 对象成员,先析构类对象,再析构对象成员
#include "stdafx.h" #include <iostream> using namespace std; class Clock { public: Clock() { cout << "clock的构造函数" << ","; } ~Clock() { cout << "clock的析构函数" << ","; } }; class Date { public: Date() { cout << "date的构造函数" << ","; } ~Date() { cout << "date的析构函数" << ","; } }; void main() { Clock c; Date d; system("pause"); }
在使用构造函数和析构函数时,需要特别注意对它们的调用时间和调用顺序。
在一般情况下,调用析构函数的次序正好与调用构造函数的次序相反:最先被调用的构造函数,其对应的(同一对象中的)析构函数最后被调用,而最后被调用的构造函数,其对应的析构函数最先被调用。
可以简记为:先构造的后析构,后构造的先析构,它相当于一个栈,先进后出
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。