为什么私有继承对象允许将成员函数的派生*强制转换为base *,而外部人员则不允许?

时间:2019-01-23 03:44:56

标签: c++

我正在检查关于私有继承的FAQ,我不太理解以下两个结论,有人可以解释一下吗?

用户(外部用户)都无法将Car *转换为Engine *吗?

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

  

私有继承是组成的句法变体(AKA   聚集和/或具有-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对象中都只包含一个Engine成员对象
  •   
  • 在任何情况下,用户(外部用户)都无法将Car *转换为Engine *
  •   
  • 在这两种情况下,Car类都有一个start()方法,该方法在包含的Engine对象上调用start()方法。
  •   
     

还有一些区别:

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

1 个答案:

答案 0 :(得分:4)

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

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