假设我有一个继承自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)
{
...
}
但是,我对该解决方案有三个问题:
所以,总结一下:
当我们已经完成了这些类的对象(或者只是制作它们所需的东西,甚至)时,有哪些方法可以创建一个从某些类继承的对象?
那些最常见,最简单,最不可能导致头痛和并发症的方法,无论是合乎逻辑的还是语法的?
答案 0 :(得分:0)
理想情况下,如果我可以构建一些不完整的
C
,然后只执行c = s1; c = s2;
并且仅s1
和s2
c
部分,那就太棒了每次作业都会改变。
你知道什么!您可以非常轻松地实现这种确切的语法。事实是,每个基类都有一个你继承的operator =
。它只是由派生类自己的operator =
隐藏(无论是否隐式生成)。因此,您只需将所有这些都重新纳入范围:
class C : public I, public S1, public S2
{
public:
using I::operator=;
using S1::operator=;
using S2::operator=;
};
...然后表现完全如你所描述的那样。但是,没有任何东西,基类是默认构造的,这可能会延伸你所说的“不完全构建”。遗憾的是,(?)不可能有一个有效的派生对象,其基类根本没有被初始化。
答案 1 :(得分:0)
通过继承构成是一种支持它的语言,但它被认为是次要的练习,甚至是OOP中的反模式与组合。
通过继承,您可以获得自动方法实现和转换。但是你放弃了对API的控制。并且您引入了S1
和S2
之间的耦合,因为它们的实现相互制约,它们的成员命名相同,而不会引入消歧。恕我直言,由于这种方式更加隐含,因此存在更多陷阱。
通过组合,您可以保持灵活性和细粒度控制,但代价是明确的间接......以及随之而来的实施工作。基本上,如果需要,必须复制两个API,并且在您的情况下似乎是这样。
在其他方面,它们几乎相同,您可以编写具有相同可用性的客户端代码。例如。转换和分配。
您需要或不需要以任何方式复制c'对于继承,您可以提供make_C
工具并转发c参数。 S1
和S2
必须提供您可以重复使用的任何构造方式,这两种方法都是如此。您应该能够为继承模式编写适当的c'
如果您需要将C
与其成员分开,您还需要以某种方式通过成员资格制作作品副本。
您不能使用继承使C
成为引用的外观,就像使用对组件的引用一样,可以使用成员资格构成。但是,如果您需要在C
的实例与其各自的部分之间共享身份,那么它不是真正的构图关系。
总的来说,不那么头疼的事情是不可能的,这是一个设计决定。更一般和灵活的是会员制组成,更简单的可能继承。但我不确定我是否会将其换掉。
我说设计越封闭和僵化,你肯定没有干扰继承对其专业人士来说更安全。否则,它可能是PIA并且需要在某个时间点进行重构。如果你有庞大的类,重复接口就是PIA。