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

C++菱形继承问题:如何避免printInfo函数重复调用基类方法

解决C++菱形继承中printInfo重复输出基类信息的自动化方案

核心思路是利用虚拟继承的构造顺序特性,在每个类的构造函数中注册自身的打印逻辑到统一容器,最终遍历容器完成按顺序输出——既避免重复打印基类,又无需硬写调用顺序,便于维护扩展。

实现步骤

  1. 在基类Base中维护存储打印函数的容器(如std::vector)。
  2. 每个类(含Base)在构造函数中,将自身打印逻辑以匿名函数形式加入容器。
  3. 基类提供printInfo成员函数,遍历容器执行所有注册的打印逻辑。

完整代码示例

#include <iostream>
#include <vector>

class Base {
protected:
    std::vector<void(*)()> printHandlers;
public:
    Base() {
        printHandlers.push_back([]() {
            std::cout << "Base" << std::endl;
        });
    }

    virtual void printInfo() {
        for (auto handler : printHandlers) {
            handler();
        }
    }
};

class Class1 : virtual public Base {
public:
    Class1() {
        printHandlers.push_back([]() {
            std::cout << "Class1" << std::endl;
        });
    }
};

class Class2 : virtual public Base {
public:
    Class2() {
        printHandlers.push_back([]() {
            std::cout << "Class2" << std::endl;
        });
    }
};

class Class3 : public Class1, public Class2 {
public:
    Class3() {
        printHandlers.push_back([]() {
            std::cout << "Class3" << std::endl;
        });
    }
};

int main() {
    Class3 c3;
    c3.printInfo();
    // 输出顺序:Base→Class1→Class2→Class3
    return 0;
}

方案优势

  • 自动维护顺序:完全遵循C++虚拟继承构造顺序(虚拟基类→非虚拟基类→派生类),无需手动指定调用顺序。
  • 扩展性强:新增派生类时,仅需在构造函数中添加自身打印逻辑,无需修改现有代码。
  • 无重复输出:虚拟继承保证Base仅构造一次,其打印逻辑只会被注册一次。
  • 无额外依赖:仅使用C++标准库,无需第三方库支持。

备选方案(标记位控制)

若不想依赖构造函数注册,可通过传递标记位控制基类打印次数:

#include <iostream>

class Base {
public:
    virtual void printInfo(bool& printed) {
        if (!printed) {
            std::cout << "Base" << std::endl;
            printed = true;
        }
    }
};

class Class1 : virtual public Base {
public:
    void printInfo(bool& printed) override {
        Base::printInfo(printed);
        std::cout << "Class1" << std::endl;
    }
};

class Class2 : virtual public Base {
public:
    void printInfo(bool& printed) override {
        Base::printInfo(printed);
        std::cout << "Class2" << std::endl;
    }
};

class Class3 : public Class1, public Class2 {
public:
    void printInfo() {
        bool basePrinted = false;
        Class1::printInfo(basePrinted);
        Class2::printInfo(basePrinted);
        std::cout << "Class3" << std::endl;
    }
};

此方案逻辑更直接,适合简单场景,但需修改printInfo参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 08:04:56