C++ 为什么私有继承对象允许成员函数将派生的*转换为基*而外部对象不允许?

C++ 为什么私有继承对象允许成员函数将派生的*转换为基*而外部对象不允许?,c++,C++,我正在检查一份关于私人继承的报告,我不太明白以下两个结论,有人能解释一下吗 在这两种情况下,用户(外部人员)都不能将汽车*转换为发动机*? 私有继承变体允许Car成员将汽车*转换为发动机*? 私有继承是复合的一种语法变体(AKA) 聚合和/或has-a) 例如,“汽车有发动机”关系可以用 简单的组成: class Engine { public: Engine(int numCylinders); void start(); // Starts this

我正在检查一份关于私人继承的报告,我不太明白以下两个结论,有人能解释一下吗

在这两种情况下,用户(外部人员)都不能将汽车*转换为发动机*?

私有继承变体允许Car成员将汽车*转换为发动机*?

私有继承是复合的一种语法变体(AKA) 聚合和/或has-a)

例如,“汽车有发动机”关系可以用 简单的组成:

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
};
“汽车有发动机”的关系也可以用 私人继承:

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
};
“私人继承”和“组合”有何相似之处?有 这两种变体之间有几个相似之处:

  • 在这两种情况下,每个汽车对象中只包含一个引擎成员对象
  • 在这两种情况下,用户(局外人)都不能将汽车*转换为发动机*
  • 在这两种情况下,Car类都有一个start()方法,该方法对包含的引擎对象调用start()方法
还有几个区别:

  • 如果要包含,则需要简单的组合变量 每辆车有几个引擎
  • 私有继承变量可能引入不必要的多重继承
  • 私有继承变体允许Car成员将汽车*转换为发动机*
  • 私有继承变量允许访问基类的受保护成员
  • 私有继承变体允许汽车覆盖发动机的虚拟功能
  • 私有继承变体使Car的start()方法稍微简单一些(20个字符,而不是28个字符),该方法只调用引擎的start()方法

<> > C++中的<>代码>私下<代码> >的动机是——通过隐藏类的细节,编译器可以确保其他代码(在类的自己的代码之外)不能,因此不依赖于这些细节,因此,编译器可以帮助您保证,如果将来更改这些详细信息,则不需要修改其他代码


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

还有一个区别被忽略了:私有继承将强制使用vtables。@van dench这不是必须的,基类可能没有虚函数。我很确定构造函数仍然强制vtables。@vandench构造函数不强制vtables,只有虚方法(或虚继承)强制vtables。