困惑于C ++多重继承

时间:2016-06-22 10:50:01

标签: c++ inheritance multiple-inheritance

我对C ++的更高级功能有点新鲜。昨天,我发布了以下问题,我了解了虚拟继承和可怕的死亡钻石。

Inheriting from both an interface and an implementation C++

我还通过其他链接了解到,多重继承通常是代码设计错误的标志,并且通常可以在不使用MI的情况下更好地实现相同的结果。问题是......对于以下问题,我不知道什么是更好的单继承方法。

我想为两种类型的数字点定义一个接口。输入数字点和输出数字点。接口要纤薄,只需要访问信息所需的内容。当然,绝大多数属性对于两种类型的数字点都是通用的。所以对我来说,这是一个明显的继承案例,而不是组合。

我的界面定义如下所示:

// Interface Definitions
class IDigitalPoint
{
public:
  virtual void CommonDigitalMethod1() = 0;
};

class IDigitalInputPoint : virtual IDigitalPoint
{
public:
  virtual void DigitialInputMethod1() = 0;
};

class IDigitalOutputPoint : virtual IDigitalPoint
{
public:
  virtual void DigitialOutputMethod1() = 0;
};

我的实现看起来像这样:

// Implementation of IDigitalPoint
class DigitalPoint : virtual public IDigitalPoint
{
public:
  void CommonDigitalMethod1();
  void ExtraCommonDigitalMethod2();
}

// Implementation of IDigitalInputPoint
class DigitalInputPoint : public DigitalPoint, public IDigitalInputPoint 
{
public:
  void DigitialInputMethod1();
  void ExtraDigitialInputMethod2();
}

// Implementation of IDigitalOutputPoint
class DigitalOutputPoint : public DigitalPoint, public IDigitalOutputPoint 
{
public:
  void DigitialOutputMethod1();
  void ExtraDigitialOutputMethod2();
}

那么我怎么能重新格式化这个结构,以避免MI?

7 个答案:

答案 0 :(得分:7)

"多重继承通常是代码设计错误的标志。 - 纯粹接口的父母不计入此规则。您的I*类是纯接口(仅包含纯虚函数),因此您Digital*Point类在这方面是可以的

答案 1 :(得分:1)

(多个)继承和接口往往是简单关系的不必要的并发症。

这里我们只需要一个简单的结构和很少的独立功能:

namespace example {
    struct Point { T x; T y; }

    Point read_method();
    void write_method(const Point&)
    void common_method(Point&);
    void extra_common_method(Point&);
} // example

common_method可能是Point的成员函数的候选者。 extra_common_method不常见,可能是另一个封装Point的类的候选者。

答案 2 :(得分:0)

这正是标准库 std::basic_iostream层次结构中使用虚拟继承的情况。

因此,它可能是一种罕见的情况,它真正有意义。

但是,这取决于您为清晰起见而删除的详细信息,因此无法确定是否存在更好的解决方案。

例如,为什么是与输出点不同的输入点? DigitalPoint听起来像具有属性的 thing ,可能由类建模。然而,DigitalInputPoint听起来像...... DigitalPoint以某种方式耦合到输入源。它有不同的属性吗?不同的行为?它们是什么?为什么?

答案 3 :(得分:0)

您可以访问以下链接,了解有关多重继承的更多信息 Avoid Multiple Inheritance

此外,在您的情况下,多重继承是有道理的! 如果需要,您可以使用合成。

答案 4 :(得分:0)

考虑一种不同的方法:

class DigitalPoint
{
public:
  void CommonDigitalMethod1();
  void ExtraCommonDigitalMethod2();
}

// Implementation of IDigitalInputPoint
class DigitalInputPoint
{
public:
  void CommonDigitalMethod1();
  void DigitialInputMethod1();
  void ExtraDigitialInputMethod2();
}

// Implementation of IDigitalOutputPoint
class DigitalOutputPoint
{
public:
  void CommonDigitalMethod1();
  void DigitialOutputMethod1();
  void ExtraDigitialOutputMethod2();
}

要像这样使用:

template <class T>
void do_input_stuff(T &digitalInputPoint){
    digitalInputPoint.DigitialInputMethod1();
}

通过更清晰的设计和更少的耦合,您可以更轻松地实现更好的性能。 唯一的缺点是接口是由用法隐式定义的。这可以通过记录模板期望的内容来减轻,最终您可以在概念中执行此操作,让编译器为您检查。
另一个缺点是你不能再拥有vector<IDigitalPoint*>

答案 5 :(得分:0)

你真的确定需要3个接口吗?

{{1}}

答案 6 :(得分:0)

您可以使用合成而不是继承。 Live Example

如果子类不使用DigitalPoint的功能,则可以尝试使用CRTP。如果你不理解CRTP,可能会让人感到困惑,但如果它正确适合,它就像一个魅力。 Live Example