虚拟继承与可怕的钻石 [英] Virtual Inheritance and dreaded diamond

查看:91
本文介绍了虚拟继承与可怕的钻石的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在可怕的钻石问题上遇到了麻烦. 提醒一下,这是此问题的经典类层次结构:

I am having a hard time with a dreaded diamond problem. For a reminder, here is the classical class hierarchy of this problem:

    B
   / \
 C1   C2
   \ /
    D

要解决此问题,标准的解决方案是使C1和C2使用虚拟继承从B继承.

To solve it, the standard solution is to make C1 and C2 use virtual inheritance to inherit from B.

我的问题是B和C1来自无法修改的SDK. 在下面的示例中,我无法使 SubClassB 继承自 Base . 类:PureVirtualBase,Base和SubClassB来自我使用的SDK.我无法修改它们. SubClassA和Leaf是我的自定义类.我可以更改它们.

My problem is that B and C1 are from an SDK that I cannot modify. Example below where I cannot make SubClassB inherit virtually from Base. Classes: PureVirtualBase, Base and SubClassB are from the SDK I use. I cannot modify them. SubClassA and Leaf are my custom classes. I can change them.

     PureVirtualBase(SDK)
           |
        Base(SDK)
       /        \
 SubClassA   SubClassB(SDK)
       \        /
          Leaf

在无法更改 SubClassB 以使用来自 Base 的虚拟继承的情况下.应该怎么做:

In such a situation where SubClassB cannot be changed to use virtual inheritance from Base. How what should so that:

  • 叶子实例仅包含一个 Base
  • 尝试访问在 PureVirtualBase 中定义的纯虚拟和在 Base
  • 中实现的函数时,避免歧义
  • Leaf instance only contains one Base
  • Avoid the ambiguity when trying to access functions defined pure virtual in PureVirtualBase and implemented in Base
class PureVirtualBase
{
public:
    PureVirtualBase()
    {
        cout<<"<<PureVirtualBase::PureVirtualBase" << endl;
        cout<<">>PureVirtualBase::PureVirtualBase" << endl;
    }
    virtual int f_PureVirtualBase()=0;
};
class Base : public PureVirtualBase
{
public:
    Base(std::string id) {
        cout<<"<<Base::Base:"<<id << endl;
        m_id=id;
        cout<<">>Base::Base:"<<m_id << endl;
    }
    virtual int f_PureVirtualBase() {
       cout<<"Base::f_PureVirtualBase" << endl;
       return 1;
    }
private:
    std::string m_id;
};
class SubClassA:  public virtual Base
{
public:
    SubClassA(): Base("From SubClassA") {
        cout<<"<<SubClassA::SubClassA" << endl;
        cout<<">>SubClassA::SubClassA" << endl;
    }
};
class SubClassB:  public Base
{
public:
    SubClassB():Base("From SubClassB") {
        cout<<"<<SubClassB::SubClassB" << endl;
        cout<<">>SubClassB::SubClassB" << endl;
    }
};    
class Leaf:  public SubClassA, public SubClassB
{
public:
    Leaf():SubClassA(),  SubClassB(), Base("From Leaf") {
        cout << "<<Leaf::Leaf" << endl;
        cout << ">>Leaf::Leaf"<< endl;
    }
};
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    Leaf myleaf;
    myleaf.f_PureVirtualBase();
    return a.exec();
}

  • 如果我评论对f_PurevirtualBase的调用,它将编译,但是我有一个 警告 由于模棱两可,在中无法访问虚拟基础'Base'如果取消对此调用的注释:我收到此错误:成员的请求 "f_PureVirtualBase"不明确
  • 如果我通过类名在此调用前添加前缀 (myleaf.SubClassA :: f_PureVirtualBase()然后它可以工作,但是有些 显然是错误的,因为叶子中包含2个 Base 对象).
    • If I comment the call to f_PurevirtualBase it compiles but I have a warning that virtual base 'Base' inaccessible in 'Leaf' due to ambiguity If I uncomment this call: I get this error : request for member 'f_PureVirtualBase' is ambiguous
    • If I prefix this call by the class name (myleaf.SubClassA::f_PureVirtualBase() then it works, but something is obviously wrong as there are 2 Base contained in the Leaf Object).
    • 有任何提示吗?

      更多信息以回答评论

      我的目标体系结构比我在原始问题中提供的示例稍微复杂:

      My target architecture is slightly more complex that the sample I provided in the original question:

       PureVirtualBase(SDK)
             |
           Base(SDK)
              |
              --SubClassA
              --SubClassB(SDK)
              --SubClassC(SDK)
              --SubClassD(SDK)
      

      LeafOne:继承自SubClassA和SubClassB(SDK)

      LeafOne : inherits from SubClassA and SubClassB(SDK)

      LeafTwo:继承自SubClassA和SubClassC(SDK)

      LeafTwo : inherits from SubClassA and SubClassC(SDK)

      LeafThree:继承自SubClassA和SubClassD(SDK)

      LeafThree : inherits from SubClassA and SubClassD(SDK)

      SubClassA是我自己的私人代码.它提供了自定义功能. SDK方法应该可以将其视为基本实例. 此类不会被实例化,但是在执行某些处理时,它可以在同一环境中处理LeafOne,LeafTwo和LeafThree.

      SubClassA is my own private code. It provides custom functions. It should be able to be treated like a Base instance by SDK methods. This class won't be instantiated but it is here to be able to handle LeafOne, LeafTwo and LeafThree in the same when performing some treatment.

      推荐答案

      这表明您的设计存在问题,最简单的答案是首先避免钻石.您为示例代码选择的名称非常糟糕,以至于很难推理出您可能真正想做的事情,但是无论如何都要重新考虑您是否需要从父母双方那里继承,以及很有道理.

      This indicates a problem with your design, for which the simplest answer is avoid the diamond in the first place. Your choice of names for the example code is bad enough to make it hard to reason about what you might actually be wanting to do, but at any rate reconsider whether you need to inherit from both parents, and whether that makes sense.

      继承是OO语言中使用最广泛的构造之一,它确实解决了一个问题,但是它被用作螺丝,不是钉子,正确的工具不是锤子.

      Inheritance is one of the most abused constructs there is in OO languages, it does solve a problem, but it is used as a golden hammer everywhere else. Many times what you have in your hand is a screw, not a nail and the correct tool is not a hammer.

      这篇关于虚拟继承与可怕的钻石的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆