面试题答案
一键面试1. public继承
- 适用场景:当需要体现 “is - a” 关系,即子类是父类的一种特殊类型时使用。例如在一个图形绘制项目中,有一个
Shape
父类,Circle
、Rectangle
作为子类。Circle
是一种Shape
,所以Circle
类应该以public
方式继承Shape
类。 - 设计思路:这样继承后,子类会继承父类的所有
public
和protected
成员,并且这些成员在子类中的访问权限和在父类中一样。这使得可以在使用父类的地方使用子类,符合多态性的设计原则。例如,有一个函数draw(Shape& s)
,可以传入Circle
或Rectangle
对象,因为它们都是Shape
的子类。 - 决策依据:
- 可维护性:代码结构清晰,符合人们对现实世界中类型关系的认知,易于理解和扩展。例如新增一种图形
Triangle
,也以public
方式继承Shape
,整个系统代码结构不需要大的变动。 - 安全性:因为父类的接口在子类中保持原有的访问权限,所以不会意外暴露内部实现细节,保证了一定的安全性。
- 性能:不会引入额外的性能开销,因为这种继承方式在运行时的行为和父类是一致的,只是增加了子类特有的行为。
- 可维护性:代码结构清晰,符合人们对现实世界中类型关系的认知,易于理解和扩展。例如新增一种图形
2. private继承
- 适用场景:当子类需要复用父类的代码,但并不想暴露父类的接口,只是将父类作为实现细节时使用。比如在一个游戏开发项目中,有一个
PhysicsEngine
类用于处理物理模拟,而Character
类需要用到物理模拟的功能,但Character
的对外接口并不想暴露PhysicsEngine
的接口。 - 设计思路:
Character
类以private
方式继承PhysicsEngine
,这样PhysicsEngine
的所有public
和protected
成员在Character
类中都变成private
的,外部无法直接访问。Character
可以在内部调用PhysicsEngine
的成员函数来实现自身的物理相关功能。 - 决策依据:
- 可维护性:父类的实现细节和子类的接口分离,当父类实现改变时,只要子类调用的接口不变,子类的外部接口不会受到影响,提高了代码的可维护性。
- 安全性:父类的接口不会被外部误调用,只有
Character
类内部可以使用,增强了安全性。 - 性能:和
public
继承类似,运行时不会引入额外性能开销,但相比组合方式(另一种复用代码的方式),private
继承可能会让代码结构不够清晰,因为从类关系上看更像是 “is - a”,而实际语义是 “has - a”。
3. protected继承
- 适用场景:通常用于当你希望子类能够访问父类的部分接口,但又不想让外部直接访问这些接口时。例如在一个框架开发项目中,有一个
BaseComponent
类,一些DerivedComponent
类继承自它。BaseComponent
有一些方法是为了给子类扩展功能用的,但不应该被框架的使用者直接调用。 - 设计思路:通过
protected
继承,父类的public
和protected
成员在子类中变为protected
。这样子类及其子类可以访问这些成员,而外部代码无法访问。 - 决策依据:
- 可维护性:将父类中对子类有意义但对外部无意义的接口保护起来,避免外部误操作,同时方便子类复用和扩展,提高可维护性。
- 安全性:防止外部直接调用那些不适合外部调用的接口,增强安全性。
- 性能:同样运行时不会带来额外性能开销,不过这种继承方式在实际使用中相对较少,因为如果过度使用可能会使类之间的关系变得复杂,不利于代码理解。