如何正确解决C++多重继承中的update方法循环问题
问题解决方案:避免多重继承下的update方法无限循环
问题分析
当前代码的核心问题在于:当DerivedClassSuper中调用DerivedClass1::update(this)时,update是Base类的虚函数,虽然用类名限定调用,但传入的this是DerivedClassSuper类型的对象,因此this->updateInternal()会触发动态绑定,调用DerivedClassSuper重写的updateInternal,从而进入无限循环。
最优解决方案
方案1:直接调用基类的updateInternal(最简洁)
既然update方法的本质是调用updateInternal,直接跳过update方法,显式调用基类的updateInternal即可,完全避免虚函数的动态绑定问题。
修改后的DerivedClassSuper代码:
class DerivedClassSuper : public virtual DerivedClass1, public virtual DerivedClass2 { public: void updateInternal() override { std::cout << "DerivedClassSuper::updateInternal()" << std::endl; std::cout << "DerivedClass1::updateInternal()" << std::endl; DerivedClass1::updateInternal(); // 直接调用DerivedClass1的版本 std::cout << "DerivedClass2::updateInternal()" << std::endl; DerivedClass2::updateInternal(); // 直接调用DerivedClass2的版本 } };
方案2:给每个派生类添加非虚的update方法
如果必须保留update方法的调用形式,可以让DerivedClass1和DerivedClass2各自实现非虚的update方法,直接调用自身的updateInternal,避免触发Base类的虚函数逻辑。
修改后的代码:
class Base { public: virtual void update(Base *b1) { this->updateInternal(); } virtual void updateInternal() = 0; }; class DerivedClass1 : public virtual Base { public: void updateInternal() override { std::cout << "DerivedClass1::updateInternal()" << std::endl; } // 新增非虚的update方法,直接调用自身的updateInternal void update() { updateInternal(); } }; class DerivedClass2 : public virtual Base { public: void updateInternal() override { std::cout << "DerivedClass2::updateInternal()" << std::endl; } // 新增非虚的update方法 void update() { updateInternal(); } }; class DerivedClassSuper : public virtual DerivedClass1, public virtual DerivedClass2 { public: void updateInternal() override { std::cout << "DerivedClassSuper::updateInternal()" << std::endl; std::cout << "DerivedClass1::update(this)" << std::endl; DerivedClass1::update(); // 调用DerivedClass1的非虚update std::cout << "DerivedClass2::update(this)" << std::endl; DerivedClass2::update(); // 调用DerivedClass2的非虚update } };
方案3:修改Base的update方法,支持显式指定调用的基类版本
如果需要保留Base类update的通用性,可以添加一个模板方法,允许指定调用某个基类的updateInternal:
class Base { public: virtual void update(Base *b1) { this->updateInternal(); } virtual void updateInternal() = 0; // 模板方法,调用指定基类的updateInternal template<typename T> void updateAs(Base *b1) { static_cast<T*>(b1)->T::updateInternal(); } }; class DerivedClassSuper : public virtual DerivedClass1, public virtual DerivedClass2 { public: void updateInternal() override { std::cout << "DerivedClassSuper::updateInternal()" << std::endl; std::cout << "DerivedClass1::update(this)" << std::endl; updateAs<DerivedClass1>(this); // 显式调用DerivedClass1的updateInternal std::cout << "DerivedClass2::update(this)" << std::endl; updateAs<DerivedClass2>(this); // 显式调用DerivedClass2的updateInternal } };
效果验证
修改后运行main函数,输出会变成:
DerivedClassSuper::updateInternal() DerivedClass1::updateInternal() DerivedClass2::updateInternal()
(对应方案1的输出,其他方案输出类似,无循环)
内容的提问来源于stack exchange,提问作者extreme001
相关产品推荐
相关产品推荐

