c++ 如果您使用多个is-a继承,您是否不想使用共同基类的虚拟继承?

如果你是一个与公共继承相关的继承关系,并且拥有一个继承的钻石,你将会有以下的东西:

>流类
>从流派生的输入流和输出流类
>从两者派生的输入/输出流类

在这种情况下,如标准库(?)中所使用的那样,在iostream既是一个istream又是一个ostream的情况下,istream是一个流,ostream是一个流,而且它们是一样的流,流中任何功能,应用于iostream是有意义的,应该处理相同的底层结构。

在C中,为了可以共享在流和ostream中的流副本,它们必须被虚拟地继承。

但是,如果您愿意,您不能虚拟地继承,并且每次引用基类的成员时,都需要指定两个副本(一个在一个istream中,一个在ostream中)(通过转换或使用范围) :: blah)。

我的问题是,除了“这不是一个真正的关系,我没有使用公共继承作为句法的方便,当它不是概念上有效”或“我从来没有需要从多数派生类引用基类,所以非常小的开销是不值得的“,有理由在概念上有效地继承非虚拟且有两个副本的基类,一个对于每个姐妹中级班?

最佳答案
我们来一个简单的例子。

   B           B1   B2
   |             \ /
   D              D

在左边,我们找到一个派生自单个低音的课程。对于与Liskov替代校长有关系的关系,OO设计显然是合理的。

在右侧,B1和B2都是D的独立基,D可以使用B1 *或B2 *(或参考)进行多态访问。希望我们可以接受,这也是一个有效的OO设计(尽管Sun认为它对于Java程序员来说压力很大)。然后考虑将B1和B2中的一些基本功能考虑进来,并使其可重用:说它们都可以在任意数量的数字列表上运行,他们可以合理地授予直接/公共访问权限:

   Container<int>   Container<int>
              \     /
              B1   B2
                \ /
                 D

如果这还没有点击,也许:

   Container<int>   Container<int>
              \     /
            Ages  Heights
                \ /
             Population

可以说,Ages是一个容器< int>虽然它可能会添加一些方便的功能,如average,min,max,num_teenagers。与高地相同,可能运用不同的便利功能。显然,人口可以合理地代替年龄或高度集合(例如,size_t num_adults(Ages&); if(num_adults(my_population))…)。

这里的意思是,每个支持容器不是与进一步派生的类别(如人口)具有1:1的关系;相反,它的意思是与其立即派生的类完全为1:1。

再次,使用组合或继承是否是接口设计决策,但是以这种方式公开暴露容器不一定无效。 (如果有关于维护人口不变量,如Ages :: empty()== Heights :: empty(),容器< int>的数据变异函数可能会受到保护,而const成员函数是公开的。)

如你所见,人口与容器< int>没有明确的is-a关系并且代码可能需要明确的消歧。这是适当的当然,人口从集装箱< int>衍生出来也是可能和合理的。如果它存储一些其他数字,但这将独立于间接继承的容器。

My question is, other than “This isn’t really an is-a relationship, I used naughtily used public inheritance as a syntactic convenience when it wasn’t conceptually valid”

我看不到上述的关系或概念有效性的问题,如果你请你解释….

“I never need to refer polymorphically to the base class from the most-derived class so the incredibly small overhead isn’t worth it”

我认为很明显,我只是基于自然对象关系进行数据建模,而不是一些可疑的优化。实际使用的基础的辅助容器类实际使用,并且必须在每个基础中是独立的。

转载注明原文:c++ 如果您使用多个is-a继承,您是否不想使用共同基类的虚拟继承? - 代码日志