要清楚,我不是在问为什么/为什么多重继承是好还是坏。我从这次辩论的双方都听到了很多争论。
我想知道在C ++中是否存在任何类型的设计问题或场景,其中多重继承是实现某些目标的唯一方法,或者至少是所有其他替代方案的最佳方式。
。考虑其他事情是有道理的。显然,这个问题不适用于不支持多重继承的语言。
答案 0 :(得分:11)
如果没有多重继承,则无法执行policy-based design。因此,如果基于策略的设计是解决问题的最佳方式,那么这意味着您需要多重继承来解决您的问题,而不是所有其他选项。
如果多重继承没有被滥用(比如任何语言的所有内容),那么多重继承会非常有用。
答案 1 :(得分:5)
在某种情况下,您将从类继承并可能在Java中实现一个或两个接口。我认为这是你在c ++中使用多重继承解决的问题。
答案 2 :(得分:4)
C ++流使用多重继承:istream
和ostream
都是iostream
的父级。由于它们都继承自ios_base
,因此你有一颗钻石。
这是唯一的“合理”解决方案,因为标准库的流部分采用与算法和集合相同的行是不合理的。所以ostream的行为是多态的,而不是像Iterator(*)这样的“鸭型”接口。
只要有动态多态,就需要多次继承才能同时实现多个接口。
(*)据推测,这是因为其他任何东西都是混乱的。您必须能够编写操作流的实际函数,而不是强迫用户在任何地方使用模板。这是因为写入“某些流,我不知道什么直到运行时”是常见的,但不想操纵“某些集合,我不知道什么直到运行时”。
答案 3 :(得分:3)
如果您需要继承行为,而不仅仅是合同,则多重继承非常有用。但是,正如其他语言所证明的那样,多重继承不是解决该问题的唯一方法,而代价是使继承树更深入。因此,必须和可能只使用多重继承的情况非常罕见。
答案 4 :(得分:2)
我已经阅读了Java接口,等等,以便更好地了解这个问题的答案。接口背后的想法是创建一个抽象类,作为另一个类的模板。这里的优点是模板可以在一个具体的类中组合。例如 -
父类 - FoodStore Subclass- CoffeeShop Subclass- Bakery
使用这个继承树,FoodStore可以是Bakery或CoffeeShop,但不能同时使用。但那么我们称之为星巴克呢?
更好的方式,IMO -
父类 - 食品店 Interface- CoffeeShop Interface- Bakery
公共课星巴克推广FoodStore实施CoffeeShop,Bakery {...}你必须要了解一些Java才能理解这一点,但要掌握它。接口是相当基础的,IMO。
作为进一步的思考,也许Interfaces旨在服从“不要重复自己”。很明显,现在我提到了它。
答案 5 :(得分:1)
如果您想继承功能而不是角色,请点boost::noncopyable
(支持此功能的其他语言(与Java和C#不同)称之为 mixin )。
答案 6 :(得分:0)
正如其他答案所说:
使用纯虚拟基类作为“接口”,就像在Java(http://en.wikipedia.org/wiki/Interface_(Java))中一样,这是一个非常常见的O.O.所有O.O.模式语言,而不仅仅是Java
做基于警察的设计
但是:
答案 7 :(得分:0)
如果必须组合两个或多个第三方类层次结构,每个层次结构要求对象从层次结构自己的Base类派生,那么缺少多重继承将使您的代码变得复杂和繁琐。
namespace Object_Database {
class Object {
public:
virtual void store() ;
virtual void fetch() ;
};
}
namespace Reflectives {
class Object {
public:
virtual std::vector<std::string> > membernames();
virtual std::vector<std::string> > methodnames();
};
}
第一个层次结构允许用户创建可以与对象数据库进行序列化的对象,并要求所有这些对象都是从Object_Database :: Object类派生的。第二层次结构允许用户创建可在运行时查询其成员名称的对象,并要求所有此类对象都从Reflectives :: Object派生。
如果您需要可以同时执行这两项操作的对象,则只需编写:
class ReflectivePickle :
public Object_Database::Object,
public Reflectives::Object {
// ...
};
其他解决方案不合理。
答案 8 :(得分:0)
当基类是“接口类”时,我倾向于在C ++中使用多继承,即所有方法都是纯虚拟的基类,没有实现[记住你仍然可以定义一个实现,但是你必须明确地调用它],并且没有数据成员。非常类似于Java中的“接口”或(从我听到的)C#。
要在C ++中使用多态,你不能使用组合,你必须使用(公共)继承。
因此,如果类Bar(从Printable和Serializable继承(公开)),我可以将对象视为可打印对象,可序列化对象或Bar对象(使用指针或引用)。
有了作文,你不能这样做。
答案 9 :(得分:0)
如果你想看到一个漂亮的多重继承实现,请查看Eiffel。它们通过特征重命名解决钻石问题,远比范围分辨率简单,甚至支持直接重复继承,以便:
继承B,B,B
当需要使用这种类型的继承时。
如果您希望查看示例,他们的内核库是开源的,并且会广泛使用多重继承。