从类的实例创建一个对象(乘法)继承自

时间:2018-04-25 15:07:47

标签: c++ constructor multiple-inheritance

假设我有一个继承自I,S1和S2的C类。假设我只是一个接口,S1和S2是简单的结构,没有任何功能。没有类/结构共享任何公共成员或方法,也不继承任何其他成员或方法。

保证钻石层次结构等没有问题。结构的目的只是提供组合的替代方案。

代码看起来像这样:

class C : public I, public S1, public S2
{
  ...
};

现在,这个有用的方面是,只要我需要一个只是其中一部分的对象,我就可以简单地将一个C实例转换为S1或S2。关键是使用现有的C作为S1或S2(甚至是I)是直截了当的(也是有用的)。

然而,除了该用例之外,我还希望能够在提供S1对象和S2对象时创建C的新实例。想到的第一个(也是唯一的)事情是构造函数可以像这样工作:

C::C(const S1& s1, const S2&s2) : I(), S1(s1), S2(s2)
{
  ...
}

但是,我对该解决方案有三个问题:

  • 它需要我的额外代码和其他构造函数 C级非常不优雅,我认为必须有一个 更好的方法。
  • 它要求我的结构S1和S2提供复制构造函数(如果实现不同,则移动构造函数)。虽然这对我来说很好,即使使用默认构造函数,但它清楚地表明这不是一般解决方案,因此很糟糕或者至少不完整。
  • 由于框架的设计和我正在制作的应用程序,这个解决方案需要更多的功能和代码,而不仅仅是在准系统示例中。再一次,编写代码并不是一个问题,但只需要维护和思考的代码就更多了。最重要的是,使用简单的组合与C中的S1和S2实例最终会比较,如果不是更简洁的话。

所以,总结一下:

当我们已经完成了这些类的对象(或者只是制作它们所需的东西,甚至)时,有哪些方法可以创建一个从某些类继承的对象?

那些最常见,最简单,最不可能导致头痛和并发症的方法,无论是合乎逻辑的还是语法的?

2 个答案:

答案 0 :(得分:0)

  

理想情况下,如果我可以构建一些不完整的C,然后只执行c = s1; c = s2;并且仅s1s2 c部分,那就太棒了每次作业都会改变。

你知道什么!您可以非常轻松地实现这种确切的语法。事实是,每个基类都有一个你继承的operator =。它只是由派生类自己的operator =隐藏(无论是否隐式生成)。因此,您只需将所有这些都重新纳入范围:

class C : public I, public S1, public S2
{
public:
    using I::operator=;
    using S1::operator=;
    using S2::operator=;
};

...然后表现完全如你所描述的那样。但是,没有任何东西,基类是默认构造的,这可能会延伸你所说的“不完全构建”。遗憾的是,(?)不可能有一个有效的派生对象,其基类根本没有被初始化。

See it live on Coliru

答案 1 :(得分:0)

通过继承构成是一种支持它的语言,但它被认为是次要的练习,甚至是OOP中的反模式与组合。

通过继承,您可以获得自动方法实现和转换。但是你放弃了对API的控制。并且您引入了S1S2之间的耦合,因为它们的实现相互制约,它们的成员命名相同,而不会引入消歧。恕我直言,由于这种方式更加隐含,因此存在更多陷阱。

通过组合,您可以保持灵活性和细粒度控制,但代价是明确的间接......以及随之而来的实施工作。基本上,如果需要,必须复制两个API,并且在您的情况下似乎是这样。

在其他方面,它们几乎相同,您可以编写具有相同可用性的客户端代码。例如。转换和分配。

您需要或不需要以任何方式复制c'对于继承,您可以提供make_C工具并转发c参数。 S1S2必须提供您可以重复使用的任何构造方式,这两种方法都是如此。您应该能够为继承模式编写适当的c'

如果您需要将C与其成员分开,您还需要以某种方式通过成员资格制作作品副本。

您不能使用继承使C成为引用的外观,就像使用对组件的引用一样,可以使用成员资格构成。但是,如果您需要在C的实例与其各自的部分之间共享身份,那么它不是真正的构图关系。

总的来说,不那么头疼的事情是不可能的,这是一个设计决定。更一般和灵活的是会员制组成,更简单的可能继承。但我不确定我是否会将其换掉。

我说设计越封闭和僵化,你肯定没有干扰继承对其专业人士来说更安全。否则,它可能是PIA并且需要在某个时间点进行重构。如果你有庞大的类,重复接口就是PIA。