从子类构造/析构函数调用纯虚函数是否属于未定义行为?
结论
你的理解是错误的,这段代码不属于未定义行为,B::setEnable也不需要等到B类构造函数执行完毕才会被关联到虚表。
具体解释
- 在C++的对象构造流程中,会按照从基类到派生类的顺序依次执行构造逻辑:
- 首先分配对象内存,初始化虚指针(vptr)指向基类A的虚表
- 执行基类A的构造函数体
- 在进入派生类B的构造函数体之前,就会把虚指针修改为指向B类的虚表,此时对象的动态类型已经被识别为B类型
- 执行B类的构造函数体,初始化成员变量
- 因此你在B的构造函数体内调用
setEnable时,虚函数的决议结果就是B::setEnable,不会调用到基类A的纯虚函数,完全合法。 - 析构的逻辑刚好反过来:执行B的析构函数体期间,对象的动态类型依然是B,调用
setEnable同样会决议到B::setEnable,只有等B的析构函数体执行完成,才会把虚指针改回指向A的虚表。
注意:如果是在基类A的构造/析构函数中调用
setEnable,那此时对象的动态类型是A,调用纯虚函数才会触发未定义行为。
另外这段代码本身存在几个和你提问无关的小问题:
- B的构造、析构函数默认是private权限,无法直接实例化B类对象
- B对A的继承是默认的private继承,如果需要多态使用通常应该声明为public继承
内容的提问来源于stack exchange,提问作者Gogogo
相关产品推荐
相关产品推荐

