我正在寻找C ++中多重继承的有用示例,并在此处找到了一个用于创建Window的示例:A use for multiple inheritance?并对其进行了一些修改。概念上看起来像这样:
class Window
class Skinable // abstract
class Draggable // abstract
class DraggableSkinnableWindow : Window, Draggable, Skinnable
我认为这应该是MI有意义的好例子。由于实现一类Skinable没有意义,因此应该将其定义为abstract。
现在:如果我不使用MI的概念,这将是怎样的。 我会使用这样一个简单的层次结构:
class Window
class Dragable : public Window
class Skinable : public Dragable
class DraggableSkinnableWindow : Skinnable
我仍然希望Dragable和Skinable也是抽象的,但这是否可能?第二个例子是否是针对相同上下文但不使用MI的良好解决方案?
提前谢谢!
答案 0 :(得分:1)
虽然您的示例是多继承的可靠用例,但我不同意这样的断言:Skinnable有一个实现是没有意义的。相反,正如@devianfan在他的评论中提到的那样,你的单一继承替代方法无法对概念分类法进行建模。
关于横轴分类。窗户既可以穿着也可以拖拽,但这些品质都不依赖于它们。
考虑到,正如您的示例域所建议的那样,您的应用程序代码由一组图形用户界面元素组成。您可能希望根据其功能对子组执行操作。例如,您可以根据某些自定义操作所有skinnable元素的外观。另一方面,GUI中可能存在可拖动的元素,应该在某些用户输入事件上得到通知。窗口是属于这两个类别的一个很好的例子。
答案 1 :(得分:1)
我认为这应该是MI有意义的好例子。
只要Window, Draggable, Skinnable
不共享共同的祖先,至少不是纯抽象,否则你需要虚拟继承。
由于实现一个Skinable类没有意义,因此应该将其定义为abstract。
这有意义,例如定义属性skin
+ setter和getters。您似乎混淆了抽象类和纯抽象类。 抽象类至少有一个纯虚函数,这意味着您无法实例化它们。纯抽象类没有任何方法的任何实现,它们只包含纯虚函数,并且通常在c ++中用作实现接口概念。
如果我不使用MI的概念,这会是什么样子。第二个例子是否是针对相同上下文但不使用MI的良好解决方案?
你不能正确地做到这一点。 c ++没有区分类和接口(因为它没有在语言级别上提供这样的概念)。它与剥离java或c#接口相同。如果您手工提供所有化合物即Skinnable
,Draggable
碱基,将产生SkinnableDraggable
和/或DraggableSkinnable
(可能相当于)提供的类化合物是可能的。这是一个杀手锏。
你的例子,正如其他人提到的完全混合了不相关的概念。例如。您的Draggable
和Skinnable
必须为Windows
个。这一点并不明显,而且一般来说肯定不正确。
答案 2 :(得分:1)
我可能会喜欢这个
class Window
class Draggable : public virtual Window
class Skinnable : public virtual Window
class DraggableSkinnableWindow : Draggable, Skinnable
并分别在Draggabel
和Skinnable
中包含的纯虚拟方法中提供默认实现
class Draggable : public virtual Window {
virtual void aMethod() = 0;
void aMethodDefaultImplementation() = { //...// };
}
然后在DraggableSkinnable
内你有两个选择:
virtual void aMethod() = { aMethodDefaultImplementation() };
或
virtual void aMethod() = {// ...non-default implementation... //};
如果你需要一个默认实现(如果aMethod
不是纯虚拟的那样),那么它有一个好处就是提供默认实现,但是强制你明确地要求它(因为它纯粹是虚拟的)。