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@krizajBClientModule
通过IClientModule
和Module
==diamond继承从IModule
继承。或者我遗漏了什么?如果你的问题使用了与图表相同的类名,那就更清楚了..为什么图中没有IBase
接口?听起来像Java或C#抱歉,将纠正错误:S@krizajBClientModule
通过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
有一个方法