C++11中如何初始化派生类内被遮蔽的基类数据成员?
核心原因
C11的聚合类型定义明确要求类不能拥有基类,因此你定义的派生类D不属于聚合类型,无法使用多元素花括号列表执行聚合初始化,这是你测试的写法报错的根本原因,和成员是否被遮蔽没有直接关联,哪怕基类和派生类没有同名成员,C11下也不能直接用D der = {1, 2}这类写法初始化。
C++11 下的可行初始化方案
方案1:自定义派生类构造函数(推荐)
显式给派生类添加构造函数,在初始化列表中分别初始化基类子对象和派生类自身的成员,代码示例如下:
#include <iostream> using namespace std; int main() { struct B { int x; }; struct D: B { int x; // 自定义构造函数,参数分别对应基类的x、派生类的x D(int base_x, int derived_x) : B{base_x}, x(derived_x) {} }; B bas = {1}; cout << bas.x << endl; // 直接调用自定义构造函数初始化,无需先默认构造再赋值 D der = {1, 2}; cout << der.x << endl; // 输出派生类的x:2 cout << der.B::x << endl; // 输出基类的x:1 return 0; }
这种写法符合C++语法规范,可读性和可维护性都更好。
方案2:显式赋值基类子对象
如果不方便修改派生类的定义,可以在默认初始化后,通过限定名显式给基类成员赋值:
D der = {}; der.B::x = 1; // 给基类被遮蔽的x赋值 der.x = 2; // 给派生类自己的x赋值
这种就是你已经用到的写法,优势是不需要修改类定义,缺点是需要分多步操作,无法做到一次性初始化。
补充说明
C17标准放宽了聚合类型的限制,允许包含公开基类的类成为聚合类型,如果你可以升级到C17及以上标准,直接写D der = {{1}, 2}或者D der = {1, 2}就能正常初始化,不需要额外添加构造函数。
内容的提问来源于stack exchange,提问作者Wolf
相关产品推荐
相关产品推荐

