C++抽象类构造函数调用疑问:派生类指针场景下的机制解析
咱们把问题拆成两部分来聊,其实逻辑很清晰:
一、为什么抽象类的构造函数会被调用?
这是C++继承机制的硬性规则——只要你创建派生类对象,不管是用派生类指针还是直接声明对象,派生类的构造函数都会自动先调用它所有基类(包括抽象基类)的构造函数。
为啥要这么做?因为派生类对象里包含了基类的「子对象」(也就是基类定义的成员变量等内容),必须先把基类的部分初始化到位,才能接着初始化派生类自己的成员。哪怕基类是抽象类,这个初始化流程也不能跳过——抽象类只是不能被直接实例化,但它的成员依然需要被正确初始化,毕竟派生类继承了这些成员嘛。
就拿你给的代码来说,当执行new inherit()的时候,编译器会先调用pure_virtual的构造函数,把基类子对象初始化完毕,再调用inherit的构造函数处理派生类自己的部分。
二、会不会创建抽象类实例来存储虚表?
绝对不会!抽象类的核心特性就是不能被实例化,C++编译器会直接禁止你尝试创建抽象类的对象,这点完全不用担心。
那虚表(vtable)是怎么回事?其实虚表是属于类的,不是属于某个对象实例的。当编译器遇到带有虚函数的类(包括抽象类)时,会在编译阶段就为这个类生成对应的虚表,存在程序的只读数据段里。派生类会继承基类的虚表,然后把自己实现的虚函数(包括纯虚函数的实现)覆盖到虚表对应的位置。
每个对象里只会存一个虚表指针(vptr),这个指针会在构造函数执行的时候被设置,指向当前类的虚表。根本不需要创建抽象类的实例来存虚表——虚表从一开始就是类级别的全局资源。
补全代码后的运行示例
把你的代码补全后运行:
#include <iostream> using namespace std; class pure_virtual { public: pure_virtual() { cout << "Virtual class constructor called !" << endl; } virtual void show()=0; }; class inherit: public pure_virtual { public: inherit() { cout << "Derived class constructor called !" << endl; } void show() override { cout << "Derived show function" << endl; } }; int main() { pure_virtual* ptr = new inherit(); ptr->show(); delete ptr; return 0; }
输出结果会是:
Virtual class constructor called !
Derived class constructor called !
Derived show function
完全符合咱们刚才说的逻辑:先初始化基类子对象,再初始化派生类,最后调用派生类的虚函数。
内容的提问来源于stack exchange,提问作者SGoodman

