C++子类初始化时如何修改父类构造函数设置的受保护成员值
我对问题稍作修改,感谢大家的帮助!
解答
C++的对象构造顺序是固定的:基类构造函数最先执行,之后完成子类成员变量的初始化,最后才会进入子类构造函数的函数体。你没有办法在子类里直接拦截、修改父类构造函数本身的执行逻辑,但可以通过以下两种可行方案实现val = a + b + "!"的需求。
方案1:直接在子类构造函数体内覆写val值(无需修改Base类,成本最低)
val是Base类声明的protected成员,子类对其有直接读写权限,你只需要在Child的构造函数体里,等Base构造完成后重新给val赋值即可,完全适配你现有的类结构:
#include <string> using namespace std; class Base { public: explicit Base(string a) : a_(a), val(a + "!"){}; protected: string a_; string val; }; class Child : public Base { public: explicit Child(string a, string b) : Base(a), b_(b) { val = a + b + "!"; } protected: string b_; };
按你给出的测试用例,传入a="first ", b="second"时:
a_保持父类构造的赋值结果"first "b_赋值为"second"val最终结果为"first second!",完全符合需求。
说明:这个方案会先由父类构造给val赋一次a+"!"的初始值,之后再覆写为目标值。如果val的初始化逻辑涉及重量级资源申请、高复杂度计算,会产生少量额外开销,对于字符串这类轻量对象来说,这点开销完全可以忽略。
方案2:给Base添加子类专用的受保护构造重载(无额外开销,需修改Base类)
如果你想避免方案1的重复赋值,可以给Base类增加一个仅子类可调用的受保护构造函数,支持子类传入自定义的val初始值,在初始化阶段就拿到正确的结果:
class Base { public: explicit Base(string a) : a_(a), val(a + "!"){}; protected: // 仅子类可访问的构造重载,支持自定义val初始值 Base(string a, string custom_val) : a_(a), val(custom_val){}; string a_; string val; }; class Child : public Base { public: explicit Child(string a, string b) : Base(a, a + b + "!"), b_(b) { // 函数体无需额外赋值,初始化阶段已完成val的正确赋值 } protected: string b_; };
这个方案没有重复赋值的冗余操作,执行效率更高,唯一的前提是你有权限修改Base类的定义。
注意
不要为了省步骤给Base构造传入伪造的a参数、之后再回改a_值,这种写法会打乱父类的初始化逻辑,后续维护时极易引入隐蔽bug。
内容的提问来源于stack exchange,提问作者PepperGooooo
相关产品推荐
相关产品推荐

