类得继承与组合

本文介绍了面向对象编程中类的组合概念,通过一个具体的教授类的例子展示了如何使用组合来实现代码复用。同时对比了组合与继承的区别。

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

类的组合:

在一个类中,可以用类对象作为数据成员,即子对象。对象成员的类型是基类。实际上,对象成员的类型可以是基类,也可以是另外一个已定义的类。在一个类中以另一个类对象作为数据成员,称为类的组合。下面通过一个简单的例子来介绍一下:

例1.声明Professor(教授)类是Teacher(教师)类的派生类,另一个类BirthDate(生日),包含year,month,day等数据成员。可以将教授生日的信息加入到Professor类的声明中。

#include <iostream>
#include <string>
using namespace std;
class Teacher             //基类
{
public:
 Teacher(int n, string nam, char s)
 {
  num=n;
  name=nam;    
  sex=s;
 }
 ~Teacher(){}
 void display()
 {
  cout<<num<<endl;
  cout<<name<<endl;  
  cout<<sex<<endl;
 }
protected:
 int num;
 string name;
 char sex;
};
class BirthDate        //组合类
{
public:
 BirthDate(int y,int m,int d)
 {
  year=y;
  month=m;
  day=d;
 }
 ~BirthDate(){}
 void display()
 {
  cout<<year<<endl;
  cout<<month<<endl;
  cout<<day<<endl;
 }
private:
 int year;
 int month;
 int day;
};
class Professor:public Teacher
{
public:
 Professor(int n, string nam, char s, BirthDate b):Teacher(n, nam, s),birthday(b){}  //组合派生类的构造函数初始化
 ~Professor(){}
 void fun2()
 {
  birthday.display();
 }
private:
 BirthDate birthday;
};
void fun1(Teacher & t)    //形参是Teacher类对象的引用,实参为Teacher类的子类对象
{
 t.display();
}
int main()
{
 BirthDate bir(1960,7,30);                  //初始化
 Professor prof1(1001,"wang",'f',bir);      //初始化
 fun1(prof1);
 prof1.fun2();
 return 0;
}

类的组合和继承一样,是软件重用的重要方式。组合和继承都是有效地利用已有类的资源。但二者的概念和用法不同。通过继承建立了派生类与基类的关系,他是一种“是”的关系,如“白猫是猫”,“黑人是人”,派生类是基类的具体化实现,是基类中的一种。通过组合建立了成员类和组合类的关系,在本例中BirthDate是成员类,Professor是组合类。他们之间不是“是”的关系,而是有的关系,不能说教授(Professor)是一个生日(BirthDate),只能说教授(Professor)有一个生日(BirthDate)的属性。

### 继承组合的区别 #### 继承 继承是一种“是一个”关系,即一个是其父的一种型。通过继承,子可以复用父的方法和属性,并且可以通过重写方法来改变或扩展这些功能。在Python中,继承的实现方式是在定义时指定父。 **示例代码:** ```python class Animal: def speak(self): print("Animal speaks") class Dog(Animal): # Dog 继承自 Animal def speak(self): print("Dog barks") dog = Dog() dog.speak() # 输出: Dog barks ``` #### 组合 组合是一种“有一个”关系,即一个包含一个对象作为其成员变量。这种方式允许在一个中使用其他的功能而不必继承它们。组合提供了更高的灵活性,因为它可以在运行时动态地更改对象的行为。 **示例代码:** ```python class Engine: def start(self): print("Engine started") def stop(self): print("Engine stopped") class Car: def __init__(self): self.engine = Engine() # Car 有一个 Engine def start(self): self.engine.start() print("Car started") def stop(self): self.engine.stop() print("Car stopped") car = Car() car.start() # 输出: Engine started, Car started car.stop() # 输出: Engine stopped, Car stopped ``` ### 使用场景 #### 继承适用的场景 - 当两个之间的关系是“是一个”时,比如`Dog`是一个`Animal`。 - 当需要从现有派生新,并希望保持接口一致时。 - 当需要利用多态性,根据对象的实际型调用相应的方法时。 #### 组合适用的场景 - 当两个之间的关系是“有一个”时,例如`Car`有一个`Engine`。 - 当需要在运行时动态地改变对象行为时。 - 当希望避免由于多重继承带来的复杂性和潜在的冲突时。 - 当需要提高代码的模块化程度,降低间的耦合度时。 ### 总结 选择继承还是组合取决于具体的应用场景。如果两个之间存在明确的层次结构并且符合“是一个”的关系,则应该使用继承。而对于那些需要更高灵活性、更松散耦合的情况,或者当两个的关系更像是“有一个”的时候,组合通常是更好的选择[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值