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

发布于 2024-07-10 02:18:25 字数 174 浏览 13 评论 0原文

在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

ペ泪落弦音 2024-07-17 02:18:25

当您想要访问基类的某些成员但又不想在类接口中公开它们时,它非常有用。 私有继承也可以被视为某种组合: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
};

。为了获得相同的语义,你也可以像下面这样编写 car 类:

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
}; 

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

  • 你的意图不太清楚,
  • 它可能会导致滥用多个继承
  • 它破坏了 Engine 类的封装,因为您可以访问其受保护的成员,
  • 您可以覆盖 Engine 虚拟方法,如果您的目标是简单的组合,那么这是您不想要的

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

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
享受孤独 2024-07-17 02:18:25

Private 在很多情况下很有用。 其中之一是政策:

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

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

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

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

因为我们不希望用户拥有指向我们对象的 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:

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

蓝眸 2024-07-17 02:18:25

公共继承模型 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.

深居我梦 2024-07-17 02:18:25

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

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

安人多梦 2024-07-17 02:18:25

私有继承大多是出于错误的原因而使用的。 正如之前的答案所示,人们使用它来实现 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.

快乐很简单 2024-07-17 02:18:25

我曾在某一时刻使用过私有继承和受保护继承。

当您希望某些东西具有基类的行为,然后能够覆盖该功能,但您不希望全世界都知道它并使用它时,私有继承非常有用。 您仍然可以通过让函数返回该接口来使用私有派生类的接口。 当您可以让事物注册自己以侦听回调时,它也很有用,因为它们可以使用私有接口注册自己。

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

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.

违心° 2024-07-17 02:18:25

私有继承最有可能是一种合法的设计策略
当你处理两个与 is-a 不相关的类时,其中一个
要么需要访问另一个受保护的成员,要么需要
重新定义其一个或多个虚函数。

摘自 Scott Meyers 的《Effective C++》第 3 版第 191 页。

Private inheritance is most likely to be a legitimate design strategy
when you’re dealing with two classes not related by is-a where one
either needs access to the protected members of another or needs to
redefine one or more of its virtual functions.

From Scott Meyers Effective C++ 3rd Edition page in 191.

带刺的爱情 2024-07-17 02:18:25

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

  • 链表
  • 通用数组(抽象)
  • 简单数组(从通用数组继承)
  • 大数组(从通用数组继承)

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

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

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 {
    // ...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文