C++ 继承C++;(钻石恐惧)

C++ 继承C++;(钻石恐惧),c++,inheritance,C++,Inheritance,我在继承方面有以下问题(我很想用谷歌搜索它,但似乎不知道正确的关键字) 我有一个Module类,它实现了IModule与函数a()的接口。我还有ClientModule类,它继承Module类,并实现IClientModule接口和继承IModule接口的函数B()。这就是我开始遇到歧义和双重继承问题的地方 下面是一个类图,该类图应该能更详细地说明这个问题: 我需要使用IModule接口和IClientModule接口分别访问Module类和ClientModule,该接口还提供对IModul

我在继承方面有以下问题(我很想用谷歌搜索它,但似乎不知道正确的关键字)

我有一个
Module
类,它实现了
IModule
与函数
a()
的接口。我还有
ClientModule
类,它继承
Module
类,并实现
IClientModule
接口和继承
IModule
接口的函数
B()
。这就是我开始遇到歧义和双重继承问题的地方

下面是一个类图,该类图应该能更详细地说明这个问题:


我需要使用
IModule
接口和
IClientModule
接口分别访问
Module
类和
ClientModule
,该接口还提供对
IModule
接口的访问。

使IClientModule不继承IModule(并可能将其重命名为IClient)。在ClientModule中,只需从模块继承并实现IClient

或者,阅读您的评论后编写的替代解决方案:

使ClientModule类从IClientModule继承,如示例所示。但是,不从模块继承,只需为ClientModule提供一个模块成员变量,并在需要时将调用转发到此成员。大概是这样的:

class IModule { virtual void A() {} };
class Module : public IModule { ... };
class IClientModule : public IModule { virtual void B() {} };

class ClientModule : public IClientModule 
{
    // ...
    virtual void A() { _module.A(); }

private:
    Module _module;
};

但是,最好还是避免将这些内容混合在一起,并使用我的原始解决方案

使IClientModule不继承IModule(并可能将其重命名为IClient)。在ClientModule中,只需从模块继承并实现IClient

或者,阅读您的评论后编写的替代解决方案:

使ClientModule类从IClientModule继承,如示例所示。但是,不从模块继承,只需为ClientModule提供一个模块成员变量,并在需要时将调用转发到此成员。大概是这样的:

class IModule { virtual void A() {} };
class Module : public IModule { ... };
class IClientModule : public IModule { virtual void B() {} };

class ClientModule : public IClientModule 
{
    // ...
    virtual void A() { _module.A(); }

private:
    Module _module;
};


但是,最好还是避免将这些内容混合在一起,并使用我的原始解决方案

您遇到了“钻石继承”问题。钻石遗产在这里和其他地方已经讨论过很多次了。将
类模块
类IClientModule
类IModule
继承虚拟化。这不是一个完美的解决方案;有时魔法有效,有时无效。如果它不起作用,通常是对继承的要求太高。

您遇到了“钻石继承”问题。钻石遗产在这里和其他地方已经讨论过很多次了。将
类模块
类IClientModule
类IModule
继承虚拟化。这不是一个完美的解决方案;有时魔法有效,有时无效。如果它不起作用,通常是对继承的要求太高。

如果你的问题使用与图表相同的类名,那就更清楚了。
IBase
接口为什么不在图中?听起来像Java或C#抱歉,将纠正错误:S@krizajB
ClientModule
通过
IClientModule
Module
==diamond继承从
IModule
继承。或者我遗漏了什么?如果你的问题使用了与图表相同的类名,那就更清楚了..为什么图中没有
IBase
接口?听起来像Java或C#抱歉,将纠正错误:S@krizajB
ClientModule
通过
IClientModule
Module
==diamond继承从
IModule
继承。或者我遗漏了什么?但是我希望IClientModule继承IModule,所以我可以用它获得完全访问权(IModule和IClientModule)“用它获得完全访问权”是什么意思?如果您的类继承自IModule和IClient,您可以在ClientModule实例上调用这两个接口的方法。我无法访问所需的同一接口中的IModule函数和IClientModule函数。我用解决此问题的替代解决方案更新了我的答案。@krizajB-一般来说,在父类中设计派生类行为不是一个好主意。如果类
IClientModule
不依赖于任何
IModule
功能,则使
IClientModule
IModule
派生就是反手编程。这不是个好主意。虽然虚拟继承可能会解决您的特定问题,但遵循Wilbert的建议通常是更好的建议。但我希望IClientModule继承IModule,因此我可以使用它获得完全访问权(IModule和IClientModule),“使用它获得完全访问权”是什么意思?如果您的类继承自IModule和IClient,您可以在ClientModule实例上调用这两个接口的方法。我无法访问所需的同一接口中的IModule函数和IClientModule函数。我用解决此问题的替代解决方案更新了我的答案。@krizajB-一般来说,在父类中设计派生类行为不是一个好主意。如果类
IClientModule
不依赖于任何
IModule
功能,则使
IClientModule
IModule
派生就是反手编程。这不是个好主意。虽然虚拟继承可能会解决您的特定问题,但遵循Wilbert的建议通常是更好的建议。一般来说,应该避免菱形继承。有时不能,但在这里,他从一开始就指定了所有内容,因此解决方案应该是以不同的方式分解问题……他的情况真的配置了钻石“问题”吗?我的意思是,
IModule
没有状态,因此有两个实例的可能性不会导致任何附带影响。在注意到这一点之前,我正要提出同样的建议。是的,这是钻石问题,因为
IModule
有一个方法