何时多重继承是唯一合理的解决方案?

时间:2009-07-07 18:37:37

标签: c++ multiple-inheritance

要清楚,我不是在问为什么/为什么多重继承是好还是坏。我从这次辩论的双方都听到了很多争论。

我想知道在C ++中是否存在任何类型的设计问题或场景,其中多重继承是实现某些目标的唯一方法,或者至少是所有其他替代方案的最佳方式。

。考虑其他事情是有道理的。

显然,这个问题不适用于不支持多重继承的语言。

10 个答案:

答案 0 :(得分:11)

如果没有多重继承,则无法执行policy-based design。因此,如果基于策略的设计是解决问题的最佳方式,那么这意味着您需要多重继承来解决您的问题,而不是所有其他选项。

如果多重继承没有被滥用(比如任何语言的所有内容),那么多重继承会非常有用。

答案 1 :(得分:5)

在某种情况下,您将从类继承并可能在Java中实现一个或两个接口。我认为这是你在c ++中使用多重继承解决的问题。

答案 2 :(得分:4)

C ++流使用多重继承:istreamostream都是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)

正如其他答案所说:

但是:

答案 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

当需要使用这种类型的继承时。

如果您希望查看示例,他们的内核库是开源的,并且会广泛使用多重继承。

http://sourceforge.net/projects/eiffelstudio/files/