C++ 中的公共和私有继承
从文献中我们知道,对于公共继承,子类(子类)的对象也可以被视为基类(超类)的对象。当继承是protected或private时,为什么子类的对象不能被视为超类的对象?
As we know from the literature for the public inheritance the object of child class (sub-class) also can be considered as the object of base class (super-class). Why the object of the sub-class can’t be considered as an object of super-class, when the inheritance is protected or private?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
因为你看不到它:
所以你不能在可以使用 Base 对象的地方使用 PrivateDerived 对象。
所以它永远不会表现得像基类对象。
Because you can't see it:
So you can not use a PrivateDerived object where a Base object could be used.
So it will never act like a Base class object.
一般来说,您会在文献中(以及此处的其他答案)发现
protected
/private
继承意味着该类不能用作base
。事实(其他一些答案暗示了这一点)是,只有继承的可见性受到操作的影响。派生
类是一个基
类,即使外部代码无法看到它。任何
friend
或类都能够利用这种关系:现在,虽然技术上是这样,但从语义上讲,当您使用
private
继承时,您试图建模的不是一种is-a
,而是一种implemented-in-terms-of
关系。这是重要的部分:在阅读代码时,如果您看到private
继承,您不应该考虑is-a,而是implemented-in-terms-of。In general you will find in literature (and in other answers here) that
protected
/private
inheritance imply that the class cannot be used as abase
. The fact (some other answer hints into this) is that only the visibility of the inheritance is affected by the operation. Thederived
class is abase
class, even if external code cannot see it.Any
friend
or the class will be able to make use of that relationship:Now, while technically this is the case, semantically when you use
private
inheritance you are trying to model not anis-a
but rather aimplemented-in-terms-of
relationship. This is the important part: while reading code, if you seeprivate
inheritance you should not think on is-a but implemented-in-terms-of.简而言之,因为私有继承是实现的继承,而不是接口的继承。私有子类
Derived
对象不是Base
,但是是根据Base
实现的代码>.Base
的公共和受保护成员对于Derived
可见,但它们变为私有,因此外部世界无法访问。因此,私有继承可以被认为是一种特殊的组合形式,实际上在实践中很少需要这种形式。 (受保护的继承实际上从来都不是——事实上,甚至可能连 Bjarne Stroustrup 也不知道受保护的继承意味着什么。)In brief, because private inheritance is inheritance of implementation, not that of interface. A private subclass
Derived
object is not aBase
, but is implemented in terms ofBase
. The public and protected members ofBase
are visible forDerived
, but they become private, thus inaccessible for the outside world. Thus private inheritance can be thought of as a special form of composition, which is in fact rarely needed in practice. (And protected inheritance is practically never - in fact probably even Bjarne Stroustrup doesn't know what protected inheritance means.)当考虑该机制如何工作时,“为什么”很简单:因为受保护和私有继承意味着以这种方式工作。
但这可能不足以回答问题的意图。您可能会问“如果不能将生成的对象用作基类的实例,为什么拥有私有继承和受保护继承?”
嗯,非公共继承旨在促进两个类之间的“根据...实现”关系(而公共继承则促进“is-a”关系)。换句话说,您打算重用部分或全部基类功能来为您自己的消费者提供服务。
这种情况几乎总是通过聚合而不是继承(即,拥有“基”类的成员对象)来更好地实现,而且我什至可以说,非公共继承是更好的东西。
请查看此,以获取对上述内容进行扩展的较长文章。
更新:正如下面的评论者所说,在某些(诚然罕见)的情况下,非公共继承提供了否则不可能实现的架构功能机制。请务必阅读它们,因为探索语言的边缘可能会很有启发。但无论如何,尽量少做。
The "why" is simple when considering how the mechanism works: because protected and private inheritance are meant to work that way.
This is probably not enough to answer the question's intent though. You might ask "and why have private and protected inheritance if you can't use the resulting objects as instances of the base class?"
Well, non-public inheritance is meant to facilitate the "is implemented in terms of" relationship between two classes (whereas public inheritance facilitates the "is-a" relationship). In other words, you intend to reuse part or all of the base class functionality to provide services to your own consumers.
This scenario is almost always better implemented by aggregation instead of inheritance (i.e., having a member object of the "base" class), and I would go so far as to say that non-public inheritance is something better left alone.
Take a look at this for a longer write-up that expands on the above.
Update: as the commenters below state, there are some (admittedly rare) cases where non-public inheritance provides the mechanism for architectural functionality that would not otherwise be possible. Do read them, as exploring the edges of a language can be quite enlightening. But try to do it as little as you can anyway.
public
继承服务于 is-a 关系的目的。也就是说:private
继承服务于has-a关系的目的。您可以使用容器模型使用私有继承编写几乎任何类:可以重写(并且为了清晰起见,通常应该重写):
protected
继承类似于private,但实际上几乎不应该使用(Scott Meyers 和 Herb Sutter 都在各自的书中给出了这样做的原因)。
public
inheritance serves the purpose of the is-a relationship. That is:private
inheritance serves the purpose of the has-a relationship. You can write almost any class using private inheritance using a container model instead:can be rewritten (and more often than not, should be rewritten for clarity):
protected
inheritance is similar toprivate
, but in reality should almost never be used (Scott Meyers and Herb Sutter both give reasons for this in their respective books).您可以将公共/受保护/私有继承视为任何类成员的可访问性:这只是“您想要显示多少”的问题。
私有(或受保护,以稍微不同的方式)继承是一种不向外界显示的关系。因此,您不能将派生类型的对象视为其私有基,因为您无法“看到”这种关系是否存在。
You can think of public / protected / private inheritance like accessibility for any class member : it a matter of 'how much you want to show'.
A private (or protected, in a slightly different way) inheritance is a relationship which is not shown the outside world. As such, you can't treat an object of a derived type as its private base, because you don't get to "see" that this relationship even exists.
它当然可以被视为超类的对象。但是,这种考虑仅限于(通过 public/protected/private 继承修饰符),但仅限于本身(私有继承)或其子类(受保护的继承)。
所有外部对象都不允许被视为类,类似于它们不允许访问受保护或私有方法或变量。如果表达得当的话,这个类比是相当恰当的。
因此,类本身、它的子类(和朋友)可以将其视为一种 is-a 关系,但外部世界不允许这样做。
以下代码显示了这一点:
请注意,xxxSubClass 类如何从其超类派生并不重要。 这都是关于超类如何从 Base 派生,这是应该的。
编译器适当地抱怨:
It can certainly be considered an object of the super-class. However, such consideration is restricted (by the public/protected/private inhertiance modifier) to but only by itself (private inheritance) or it's sub-classes (protected inheritance).
All external objects are not allowed to considered the class as such, similar to how they not allowed to access protected or private methods or variables. The analogy is rather fitting, if expressed properly.
So, the class itself, its subclasses (and friends) can see this as an is-a relationship, but the outside world is not permitted to do so.
The following code shows this in action:
Note that it doesn't matter how the xxxSubClass-classes derive from their super-classes. It's all about how the super-classes derive from Base, which is as it should be.
The compiler complains appropriately: