为什么我们实际上需要 C++ 中的 Private 或 Protected 继承?
在 C++ 中,我想不出我想从 a 继承 private/protected 的情况 基类:
class Base;
class Derived1 : private Base;
class Derived2 : protected Base;
真的有用吗?
In C++, I can't think of a case in which I would like to inherit private/protected from a
base class:
class Base;
class Derived1 : private Base;
class Derived2 : protected Base;
Is it really useful?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
当您想要访问基类的某些成员但又不想在类接口中公开它们时,它非常有用。 私有继承也可以被视为某种组合:C++ faq-lite 给出了下面的例子来说明这个说法
。为了获得相同的语义,你也可以像下面这样编写 car 类:
但是,这种做法有几个缺点:
It is useful when you want to have access to some members of the base class, but without exposing them in your class interface. Private inheritance can also be seen as some kind of composition: the C++ faq-lite gives the following example to illustrate this statement
To obtain the same semantic, you could also write the car Class as follow:
However, this way of doing has several disadvantages:
Private 在很多情况下很有用。 其中之一是政策:
是部分类模板特化是这个设计问题的答案吗?。
它有用的另一个场合是禁止复制和分配:
因为我们不希望用户拥有指向我们对象的
noncopyable*
类型的指针,所以我们私有地派生。 这不仅适用于不可复制的类,还适用于许多其他此类(策略是最常见的)。Private can be useful in quite a few circumstances. Just one of them are policies:
Is partial class template specialization the answer to this design problem?.
Another occasion where it is useful is to forbid copying and assigning:
Because we don't want that the user has a pointer of type
noncopyable*
to our object, we derive privately. That counts not only for noncopyable, but many other such classes too (policies being the most common).公共继承模型 IS-A。
非公共继承模型是根据术语实现的。
遏制模型 HAS-A,相当于 IS-IMPLMENTED-IN-TERMS-OF。
围绕主题进行讨论。 他解释了何时选择非公共继承而不是包含的实现细节。
Public inheritance models IS-A.
Non-public inheritance models IS-IMPLEMENTED-IN-TERMS-OF.
Containment models HAS-A, which is equivalent to IS-IMPLEMENTED-IN-TERMS-OF.
Sutter on the topic. He explains when you'd choose non-public inheritance over containment for implementation details.
例如,当您想要重用类的实现而不是接口并覆盖其虚拟函数时。
For instance, when you want to reuse the implementation, but not the interface of a class AND override its virtual functions.
私有继承大多是出于错误的原因而使用的。 正如之前的答案所示,人们使用它来实现 IS-IMPLMENTED-IN-TERMS-OF,但根据我的经验,保留副本总是比从类继承更干净。 另一个早期的答案,即关于 CBigArray 的答案,提供了这种反模式的完美示例。
我意识到,在某些情况下,由于过度使用“受保护”, has-a 可能不起作用,但修复损坏的类比破坏新类更好。
Private inheritance is mostly used for wrong reason. People use it to IS-IMPLEMENTED-IN-TERMS-OF, as indicated in an earlier answer, but in my experience it's always more clean to keep a copy rather than inherit from class. Another earlier answer, the one about CBigArray, provides a perfect example of this anti-pattern.
I realize that there may be cases when has-a does not work due to over-zealous use of "protected", but it's better to fix the broken class than to break a new class.
我曾在某一时刻使用过私有继承和受保护继承。
当您希望某些东西具有基类的行为,然后能够覆盖该功能,但您不希望全世界都知道它并使用它时,私有继承非常有用。 您仍然可以通过让函数返回该接口来使用私有派生类的接口。 当您可以让事物注册自己以侦听回调时,它也很有用,因为它们可以使用私有接口注册自己。
当您有一个从另一个类派生有用功能的基类,但您只希望其派生类能够使用它时,受保护的继承特别有用。
I've used both private and protected inheritence at one point or other.
Private inheritence is useful when you want something to have the behaviour of the base class, and then be able to override that functionality, but you don't want the whole world to be aware of it and use it. You can still use the interface of a privately derived class by having a function return that interface. It's also useful when you can have things register themselves to listen for callbacks as they can register themselves using the private interface.
Protected inheritence is especially useful when you have a base class that derives useful functionality from another class but you only want its derived classes to be able to use it.
摘自 Scott Meyers 的《Effective C++》第 3 版第 191 页。
From Scott Meyers Effective C++ 3rd Edition page in 191.
我曾经将这些数据结构实现为类:
大数组的接口使它看起来像一个数组,但是,它实际上是一个固定大小的简单数组的链表。 所以我这样声明:
I once implemented these data structures as classes:
The big array's interface would make it look like an array, however, it was actually a linked list of fixed-size simple arrays. So I declared it like this: