受保护继承的实际用途是啥?

Posted

技术标签:

【中文标题】受保护继承的实际用途是啥?【英文标题】:What is the practical use of protected inheritance?受保护继承的实际用途是什么? 【发布时间】:2013-12-14 05:30:27 【问题描述】:

公共继承很容易。

A : public B 表示每个 A 都是 B。在大多数编程语言中,例如 vb.net 和 Objective-c,这是唯一的继承类型。

私有继承也简单但没有意义

A :私有 B 表示 A 由 B 实现。但是,这是没有意义的,因为这意味着 A 应该包含 B。所有权意味着更少的耦合,没有缺点。

那么我们就有了受保护的继承。

谁能给我解释一下这到底是为了什么?有人说这是一种“关系”。我还不是很清楚。

是否有人有一些示例案例,其中人们以良好的模式(和良心)将受保护的继承用于实际生产用途?

【问题讨论】:

我可能是错的,但我想我读过一本黄金 C++ 书籍(不记得具体是哪一本),protected 继承是(几乎?)废话和(几乎?)从未使用过。就像“保留以备将来使用”一样。但是,再一次,我可能会撒谎:) this answer by Johannes Schaub 实际上找到了一个用例。它仍然称其为“很少有用”。 或者试试this one 而且私有继承也几乎没用,因为它应该是所有权。 @JimThio 除非所有权不起作用。 (Mixins 就是一个很好的例子。)更一般地说,当您想要公开基类的部分(但不是全部)接口时,私有继承也是一种实用的解决方案。 using 比转发函数简单很多。 【参考方案1】:

私有继承也简单但没有意义

A :私有 B 表示 A 由 B 实现。但是,这是没有意义的,因为这意味着 A 应该包含 B。所有权意味着更少的耦合,没有缺点。

您可能看不到私有继承的原因并不意味着它没有意义。 在某些情况下,私有继承是有原因的。乍一看,您是对的,私有继承意味着就像聚合一样具有关系,并且私有继承具有(稍微)更紧密的耦合。

倾向于私有继承而不是聚合的原因可能有以下几点:

通过私有继承,您也可以继承 typedef。在某些情况下(例如特征类),私有继承只是在基类中重新 typedef 大量 typedef 的替代方法。 在极少数情况下,您必须“真正的”(即公共)基类之前初始化成员。实现这一目标的唯一方法是使该成员成为在公共基类之前继承的私有基类。 有时您需要访问成员的受保护成员。如果您无法更改成员类本身,则必须使用私有继承来访问它们。 如果成员没有自己的数据成员,它仍会占用空间。将其设为私有基类可以优化空基类,从而减小类对象的大小。 如需更多积分,请参见下方 James 的 cmets

这些原因显然是技术原因,有些人甚至会说“黑客”。但是这样的原因是存在的,所以私有继承也不是完全没有意义的。它只是不是“纯 OO 风格”——但 C++ 也不是纯 OO 语言。

一旦你理解了私有继承,保护继承的原因就很简单了:

如果您有理由私下继承某些东西并且希望派生类可以访问这些好处(即,您的类或 typedef 的潜在成员),请使用受保护的继承。显然,私有继承应该很少使用,而受保护的继承更是如此。

【讨论】:

值得指出的是,在Smalltalk 中,原始继承更接近于私有继承,而不是C++ 中的公共继承。继承最初旨在支持共享实现,共享接口。 当然,您可能错过了私有继承最常见的原因:基类提供了一个可定制的实现,使用模板方法模式,您必须重写它的虚函数。 更不用说有时,您实现特定接口的事实是您的客户的实现细节。 GUI 小部件是 GUI 事件侦听器这一事实仅涉及小部件本身(以及它在哪里注册事件)。 @JamesKanze 感谢您的补充。我担心如今支持共享实现并不被视为继承的好理由,因为人们往往会被“一切都必须是纯 OO”的心态所毒害。 关于“纯 OO”:正如我上面提到的,在该术语的发明者(也是 Smalltalk 的作者之一)的心目中,继承只是实现的继承。第一种使用 OO 标签的语言使用了鸭子类型,因此不需要继承接口。 (有关其工作原理的示例,请参见今天的 Python。)【参考方案2】:

保护继承的主要动机是正交性。 在所有其他情况下,您拥有三种不同的访问控制: 私有的、受保护的和公共的。为什么要继承 不同的?在实践中,有人可能会争辩说没有必要 或一般用于受保护的访问。这可能夸大了 情况如此,但可以肯定的是,受保护的东西要少得多 私人或公共。

另外,私有继承也不是毫无意义的,事实上, 对应于继承的原始用途。只要 执行实现的基类使用虚函数 派生类必须重载,不能使用容器。

【讨论】:

我曾经使用受保护的虚拟库来管理链接器各种传递的命令行参数;每个 pass 都由它自己的类型处理,并且链接器类型是从每个 pass 类型私有派生的。事后看来,我不确定这是一个好的设计还是只是在炫耀。

以上是关于受保护继承的实际用途是啥?的主要内容,如果未能解决你的问题,请参考以下文章

带有受保护数组属性的 php 继承让我很头疼

CSRF 保护的真正用途是啥?

公共/受保护/私有继承的问题

“受保护的内部”范围的目的是啥[重复]

继承公共/受保护/私有构造函数

具有受保护可见性的变量的风险是啥