面试 - 继承和组合

本文探讨了C++中继承和组合这两种复用技术的优缺点。继承通过Is-a关系扩展父类,但可能导致高耦合;组合通过Has-a关系减少耦合度,提高灵活性,但在某些场景下可能增加对象数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

请简单描述c++中继承和组合的优缺点?

继承与组合的优缺点

  类继承和对象组合是复用的两种最常用的技术。

一:继承

  继承是Is a 的关系,比如说cStudent继承Person,则说明Student is a Person。继承的优点是子类可以重写父类的方法来方便地实现对父类的扩展。

  继承的缺点有以下几点:

  ①:父类的内部细节对子类是可见的。

  ②:子类从父类继承的方法在编译时就确定下来了,所以无法在运行期间改变从父类继承的方法的行为。

  ③:如果对父类的方法做了修改的话(比如增加了一个参数),则子类的方法必须做出相应的修改。所以说子类与父类是一种高耦合,违背了面向对象思想。

二:组合

  组合也就是设计类的时候把要组合的类的对象加入到该类中作为自己的成员变量。

  组合的优点:

  ①:当前对象只能通过所包含的那个对象去调用其方法,所以所包含的对象的内部细节对当前对象时不可见的。

  ②:当前对象与包含的对象是一个低耦合关系,如果修改包含对象的类中代码不需要修改当前对象类的代码。

  ③:当前对象可以在运行时动态的绑定所包含的对象。可以通过set方法给所包含对象赋值。

  组合的缺点:①:容易产生过多的对象。②:为了能组合多个对象,必须仔细对接口进行定义。

由此可见,组合比继承更具灵活性和稳定性,所以在设计的时候优先使用组合。只有当下列条件满足时才考虑使用继承:

  • 子类是一种特殊的类型,而不只是父类的一个角色
  • 子类的实例不需要变成另一个类的对象
  • 子类扩展,而不是覆盖或者使父类的功能失效
### 多重继承与菱形继承的概念 多重继承是指一个类可以从多个父类派生,从而继承它们的属性方法。然而,在某些情况下,这种设计可能导致复杂的继承结构以及潜在的问题——最典型的就是所谓的“菱形继承”问题。 #### 菱形继承 当两个子类分别继承自同一个基类,而另一个类又同时继承这两个子类时,就会形成一种类似于菱形的继承关系。在这种情况下,如果子类尝试访问来自共同祖先的方法或变量,则可能会引发歧义[^1]。 以下是几种主流编程语言对此问题的不同处理方式: --- ### C++ 中的解决方案 C++ 支持多重继承,并允许开发者通过 `virtual` 关键字解决菱形继承带来的二义性问题。具体来说,声明虚基类可以让编译器知道应该只保留一份公共基类实例副本,而不是每条路径都创建独立的一份。 ```cpp class Base { public: void show() { std::cout << "Base Class"; } }; // 使用 virtual 继承来消除重复拷贝 class DerivedA : public virtual Base {}; class DerivedB : public virtual Base {}; class FinalDerived : public DerivedA, public DerivedB {}; int main(){ FinalDerived obj; obj.show(); // 正确调用了唯一的 Base 类版本 } ``` 上述代码片段展示了如何利用虚拟继承机制规避冲突[^4]。 --- ### Java 对此的态度 相比之下,Java 并不支持传统的多重继承概念(即不允许直接从超过一个非接口类型的超类那里获取成员)。不过它提供了接口作为替代方案。虽然单个类仅能扩展单一的具体实现类,但它却能够实现任意数量的抽象接口。因此,在 Java 生态系统里,“钻石问题”的风险自然就被规避掉了[^2]。 例如: ```java interface A{ default String getName(){return "A";} } interface B extends A{} interface C extends A{} class D implements B,C{ } public class Test{ public static void main(String[] args){ System.out.println(new D().getName()); // 输出:A } } ``` 这里即使存在两条通往相同根节点的道路,由于所有操作均基于契约而非实体定义完成,所以不会产生混乱状况。 --- ### Python 的应对策略 Python 同样具备完整的多继承能力,并采用了一种名为 Method Resolution Order (MRO) 的特殊算法决定优先级顺序。这意味着即便面对复杂网络状的关系图谱,也能清晰界定哪个版本应当生效[^3]。 考虑如下例子: ```python class GrandParent: def speak(self): return 'GrandParent' class ParentOne(GrandParent): pass class ParentTwo(GrandParent): def speak(self): return 'ParentTwo' class Child(ParentOne, ParentTwo): pass print(Child.mro()) # [<class '__main__.Child'>, <class '__main__.ParentOne'>, <class '__main__.ParentTwo'>, <class '__main__.GrandParent'>, <class 'object'>] child_instance = Child() print(child_instance.speak()) # 结果为 ParentTwo ``` 由上可见,默认遵循左至右广度优先原则构建搜索链条,最终选取首个匹配项执行相应逻辑。 --- ### 面试常见考察方向及相关技巧 针对此类话题,招聘方往往期望候选人不仅熟悉语法细节本身,还应掌握背后的设计哲学及其适用场景判断标准。比如询问为什么有些场合更适合选用组合模式代替显式的层次嵌套架构等等。 另外值得注意的是,除了理论阐述之外,实际动手编写示范程序亦非常重要。因为只有真正实践过后才能深刻理解其中微妙之处并灵活运用到真实世界应用开发当中去。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值