c++ - 为什么私有(private)继承对象允许成员函数将 derived* 强制转换为 base* 但外部人员不允许?

标签 c++

我正在检查 FAQ关于private-inheritance,我不太理解以下两个结论,谁能解释一下?

在这两种情况下,用户(局外人)都不能将 Car* 转换为 Engine* 吗?

私有(private)继承变体允许 Car 的成员将 Car* 转换为 Engine*?

private inheritance is a syntactic variant of composition (AKA aggregation and/or has-a).

E.g., the “Car has-a Engine” relationship can be expressed using simple composition:

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

The “Car has-a Engine” relationship can also be expressed using private inheritance:

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

How are “private inheritance” and “composition” similar? There are several similarities between these two variants:

  • In both cases there is exactly one Engine member object contained in every Car object
  • In neither case can users (outsiders) convert a Car* to an Engine*
  • In both cases the Car class has a start() method that calls the start() method on the contained Engine object.

There are also several distinctions:

  • The simple-composition variant is needed if you want to contain several Engines per Car
  • The private-inheritance variant can introduce unnecessary multiple inheritance
  • The private-inheritance variant allows members of Car to convert a Car* to an Engine*
  • The private-inheritance variant allows access to the protected members of the base class
  • The private-inheritance variant allows Car to override Engine’s virtual functions
  • The private-inheritance variant makes it slightly simpler (20 characters compared to 28 characters) to give Car a start() method that simply calls through to the Engine’s start() method

最佳答案

C++ 中private 关键字背后的动机是encapsulation -- 通过隐藏关于你的类的细节,编译器可以确保其他代码(在你的类自己的代码之外)不能也不依赖于这些细节,因此编译器帮助你保证其他代码不需要如果/当您将来更改这些详细信息时进行修改。

在这种情况下,如果您通过私有(private)继承派生子类,您就是在告诉编译器不应允许外部代码知道该继承。就外部代码而言,您的 Car 类和 Engine 类之间的关系不存在(除了作为他们不知道的实现细节关于)。另一方面,Car 类中的代码是“内部”代码,因此它会了解这种关系并在需要时利用它。这样一来,如果您更改关系(例如,如果您将 Car 更改为 Vehicle 而不是 Engine 的子类),您可能需要重写一些Car 类中的代码,但您不必出去修复其他任何依赖于 Car 子类 Engine 的代码,因为从一开始就不允许外部代码依赖这种关系。

关于c++ - 为什么私有(private)继承对象允许成员函数将 derived* 强制转换为 base* 但外部人员不允许?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54319744/

相关文章:

c++ - 如何正确清除内存?

c++ - 无法打开共享对象文件 libmysqlclient.so.18

c++ - OpenCL 程序构建错误 : source file is not valid UTF-8

c++ - 令人困惑的 (*this) 指针转换

c++ - 在写入高带宽数据流时如何最好地管理 Linux 的缓冲行为?

c++ - 在eclipse中运行配置

c++ - 类声明中固定大小的 C 样式数组

c++ - 使用 CUDA/NVCC 传递给函数时动态结构成员损坏

c++ - 打印十六进制?

c++ - VTK继承问题