You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++菱形继承问题:子类如何分别继承不同父类的属性值?

C++菱形继承:自由选择父类属性值的解决方案

问题描述

在菱形继承场景下:

  • 基类A的带参构造函数初始化_hp=10、_ep=10、_ad=0
  • 类B、C均虚继承A,B构造函数将_hp设为100、_ep设为50、_ad设为20;C构造函数将_hp设为100、_ep设为100、_ad设为30
  • 类D同时继承B和C,期望D继承B的_ep(50)、C的_hp(100)和_ad(30),但实际输出中_ep始终为100(来自C),结果受D的继承顺序影响,需要实现自由访问任意父类属性值的效果。

最小可复现代码

#include <iostream>
#include <string>

class A
{
public :
    A(){
        return ;
    };
    A(std::string name) : _hp(10), _ep(10), _ad(0){
        std::cout << "A object created !" << std::endl;
        return ;
    };
    ~A(){
        std::cout << "A object " << this->_name << " destroyed." << std::endl;
        return ;
    };

protected:
    std::string _name;
    int         _hp;
    int         _ep;
    int         _ad;
};

class B : virtual public A
{
public :
    B(){
        return ;
    };
    B(std::string name) : A(name){
        std::cout << "B object created !" << std::endl;
        this->_hp = 100;
        this->_ep = 50;
        this->_ad = 20;
        return ;
    };
    ~B(){
        std::cout << "B object " << this->_name << " destroyed." << std::endl;
        return ;
    };
};

class C : virtual public A
{
public :
    C(){
        return ;
    };
    C(std::string name) : A(name){
        std::cout << "C object created !" << std::endl;
        this->_hp = 100;
        this->_ep = 100;
        this->_ad = 30;
        return ;
    };
    ~C(){
         std::cout << "C object " << this->_name << " destroyed." << std::endl;
         return ;
    };
};

class D : public B, public C
{
public :
    D(){
        return ;
    };
    D(std::string name) : A(name + "_comes_from_a"){
        this->_name = name;
        std::cout << "D object created !" << std::endl;
        this->_hp = C::_hp;
        this->_ep = B::_ep;
        this->_ad = C::_ad;
        std::cout << "HIT POINTS " << this->_hp << std::endl;
        std::cout << "ENERGY POINTS " << this->_ep << std::endl;
        std::cout << "ATTACK DAMAGE " << this->_ad << std::endl;
        return;
    }
    ~D(){
        std::cout << "D object " << this->_name << " destroyed." << std::endl;
        return ;
    };
};

int main(void)
{
     D  obj_D("TEST");
     return (0);
}

问题根源

虚继承机制下,基类A的实例在D对象中仅存在一份。构造顺序为A → B → C → D:B构造时修改了A的_ep为50,但后续C构造时又将_ep覆盖为100。因此D中尝试访问B::_ep时,实际指向的是被C修改后的共享A成员,而非B最初设置的50。

解决方案

方案1:为B、C新增独立成员存储自身属性值

让B和C各自保存自己的目标属性值,而非直接修改共享的基类成员,这样D可以直接访问这些独立变量,不受构造顺序影响:

修改B和C的定义:

class B : virtual public A
{
public:
    B() {};
    B(std::string name) : A(name), _b_hp(100), _b_ep(50), _b_ad(20) {
        std::cout << "B object created !" << std::endl;
    };
    ~B(){
        std::cout << "B object " << this->_name << " destroyed." << std::endl;
    };
protected:
    int _b_hp;
    int _b_ep;
    int _b_ad;
};

class C : virtual public A
{
public:
    C() {};
    C(std::string name) : A(name), _c_hp(100), _c_ep(100), _c_ad(30) {
        std::cout << "C object created !" << std::endl;
    };
    ~C(){
        std::cout << "C object " << this->_name << " destroyed." << std::endl;
    };
protected:
    int _c_hp;
    int _c_ep;
    int _c_ad;
};

调整D的构造函数:

D(std::string name) : A(name + "_comes_from_a"), B(name), C(name) {
    this->_name = name;
    std::cout << "D object created !" << std::endl;
    this->_hp = C::_c_hp;
    this->_ep = B::_b_ep;
    this->_ad = C::_c_ad;
    std::cout << "HIT POINTS " << this->_hp << std::endl;
    std::cout << "ENERGY POINTS " << this->_ep << std::endl;
    std::cout << "ATTACK DAMAGE " << this->_ad << std::endl;
}

方案2:在D中直接显式设置目标值

如果明确知道每个属性的期望数值,可跳过父类的属性覆盖逻辑,在D构造函数中直接设置最终值:

D(std::string name) : A(name + "_comes_from_a"), B(name), C(name) {
    this->_name = name;
    std::cout << "D object created !" << std::endl;
    // 直接设置目标属性值
    this->_hp = 100;
    this->_ep = 50;
    this->_ad = 30;
    std::cout << "HIT POINTS " << this->_hp << std::endl;
    std::cout << "ENERGY POINTS " << this->_ep << std::endl;
    std::cout << "ATTACK DAMAGE " << this->_ad << std::endl;
}

方案3:在D构造函数中覆盖父类的修改结果

利用构造顺序的特性,在D构造阶段重新设置被C覆盖的_ep值,确保最终结果符合预期:

D(std::string name) : A(name + "_comes_from_a"), B(name), C(name) {
    this->_name = name;
    std::cout << "D object created !" << std::endl;
    // 覆盖C设置的_ep值
    this->_ep = 50;
    this->_hp = 100;
    this->_ad = 30;
    std::cout << "HIT POINTS " << this->_hp << std::endl;
    std::cout << "ENERGY POINTS " << this->_ep << std::endl;
    std::cout << "ATTACK DAMAGE " << this->_ad << std::endl;
}

内容的提问来源于stack exchange,提问作者Mitsun0bu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 02:36:20