为什么我们实际上需要在 C++ 中使用 Private 或 Protected 继承?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/374399/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:01:51  来源:igfitidea点击:

Why do we actually need Private or Protected inheritance in C++?

c++inheritanceprivateprotectedc++-faq

提问by Gal Goldman

In C++, I can't think of a case in which I would like to inherit private/protected from a base class:

在 C++ 中,我想不出我想从基类继承私有/保护的情况:

class Base;
class Derived1 : private Base;
class Derived2 : protected Base;

Is it really useful?

真的有用吗?

采纳答案by Luc Touraille

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-litegives the following example to illustrate this statement

当您想要访问基类的某些成员,但又不想在类接口中公开它们时,它很有用。私有继承也可以看作是某种组合:C++ faq-lite给出了下面的例子来说明这个语句

class Engine {
 public:
   Engine(int numCylinders);
   void start();                 // Starts this Engine
};

class Car {
  public:
    Car() : e_(8) { }             // Initializes this Car with 8 cylinders
    void start() { e_.start(); }  // Start this Car by starting its Engine
  private:
    Engine e_;                    // Car has-a Engine
};

To obtain the same semantic, you could also write the car Class as follow:

为了获得相同的语义,您还可以编写汽车类如下:

class Car : private Engine {    // Car has-a Engine
 public:
   Car() : Engine(8) { }         // Initializes this Car with 8 cylinders
   using Engine::start;          // Start this Car by starting its Engine
}; 

However, this way of doing has several disadvantages:

但是,这种做法有几个缺点:

  • your intent is much less clear
  • it can lead to abusive multiple inheritance
  • it breaks the encapsulation of the Engine class since you can access its protected members
  • you're allowed to override Engine virtual methods, which is something you don't want if your aim is a simple composition
  • 你的意图不太清楚
  • 它可能导致滥用多重继承
  • 它打破了 Engine 类的封装,因为您可以访问其受保护的成员
  • 你可以覆盖 Engine 虚拟方法,如果你的目标是一个简单的组合,这是你不想要的

回答by Johannes Schaub - litb

Private can be useful in quite a few circumstances. Just one of them are policies:

Private 在很多情况下都非常有用。其中一项是政策:

Is partial class template specialization the answer to this design problem?.

分部类模板特化是这个设计问题的答案吗?.

Another occasion where it is useful is to forbid copying and assigning:

另一个有用的场合是禁止复制和分配:

struct noncopyable {
    private:
    noncopyable(noncopyable const&);
    noncopyable & operator=(noncopyable const&);
};

class my_noncopyable_type : noncopyable {
    // ...
};

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).

因为我们不希望用户拥有指向noncopyable*我们对象的类型指针,所以我们私下派生。这不仅适用于不可复制的,还适用于许多其他此类类(策略是最常见的)。

回答by Greg Rogers

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.

公共继承模型 IS-A。
非公共继承模型是 IS-IMPLEMENTED-IN-TERMS-OF。
遏制模型 HAS-A,相当于 IS-IMPLEMENTED-IN-TERMS-OF。

Sutter on the topic. He explains when you'd choose non-public inheritance over containment for implementation details.

萨特的话题。他解释了何时选择非公共继承而不是包含实现细节。

回答by Nemanja Trifunovic

For instance, when you want to reuse the implementation, but not the interface of a class AND override its virtual functions.

例如,当您想要重用实现而不是类的接口并覆盖其虚函数时。

回答by Nemanja Trifunovic

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.

私有继承主要用于错误的原因。人们将它用于 IS-IMPLEMENTED-IN-TERMS-OF,如前面的答案所示,但根据我的经验,保留副本而不是从类继承总是更干净。另一个较早的答案,关于 CBigArray 的答案,提供了这种反模式的完美示例。

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.

我意识到可能存在由于过度使用“受保护”而导致 has-a 不起作用的情况,但修复损坏的类比破坏新类要好。

回答by Daemin

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.

当您有一个从另一个类派生有用功能的基类,但您只希望它的派生类能够使用它时,受保护的继承特别有用。

回答by pyon

I once implemented these data structures as classes:

我曾经将这些数据结构实现为类:

  • Linked list
  • Generic array (abstract)
  • Simple array (inherits from generic array)
  • Big array (inherits from generic array)
  • 链表
  • 通用数组(抽象)
  • 简单数组(从泛型数组继承)
  • 大数组(从泛型数组继承)

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:

大数组的接口会让它看起来像一个数组,但它实际上是一个固定大小的简单数组的链表。所以我这样声明:

template <typename T>
class CBigArray : public IArray, private CLnkList {
    // ...