在学习c++的过程中相信大家对这几个概念都不陌生。 c++中一些常用的设计模式都是由这几种特性组合而成。本文再从整体对这个概念或者特性进行简要的介绍。

组合

c++中类之间的一种关系叫做"has-a"的关系。这种关系表示的是一个类中包含另一类的对象,体现了“有一个”的关系。这个被包含的类一般以实例对象的形式存在,而非指针对象的形式存在。请看下面的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Engine
{
public:
void start()
{
cout<<"引擎启动"<<endl;
}
}

class car
{
private:
Engine engine; //这里以实例的形式存在,而非指针,在类关系中是组合的关系
public:
void startCar()
{
engine.start(); //启动引擎
}
}

组合特点

  • 组合关系下被包含的类无法独立存在,即部分不能脱离整体存在
  • 被包含的类实例生命周期与包含类实例绑定
  • 这两个类是强拥有关系,个人理解是通过实例对象实现这个隐含的作用的,如果是指针对象的那么就不能理解为强拥有关系。

继承

继承关系是c++中特别重要的一种关系,它同样是用于描述两个类关系。用一个英文描述继承的就是"is-a",核心含义是一个类是另外一个类的特殊类型,即“是一个”的关系。具体示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Animal
{
public:
virtual void makeSound() //虚函数
{
cout<<"动物的叫声"<<endl;
}
}

class Dog: class Animal //继承关系,狗也是动物的一种,Dog类是Animal的一种特殊类型
{
public:
void makeSound()
{
cout<<"汪汪"<<endl;
}
}

继承特点

  • 强耦合关系
  • 子类继承父类的所有特性
  • 支持多态,在继承中这个多态是运行时多态;同样有编译时多态,即一个同一个函数或者方法可以定义不同的参数,这是编译时多态,也叫静态多态。

聚合

聚合也是c++中类之间关系的一种,这种关系与组合类似,也是"has-a"关系的一种。区别是在聚合关系下被包含对象的存在是以指针对象的形式存在的。请看下面的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Student
{
public:
std::string name;
...
}

class School //学校类
{
private:
std::vector<Student*> students; //学生对象的集合,聚合关系,注意这里描述学生的类型是Student*
public:

void addStudent(Student* stu)
{
students.push_back(stu);
}
}

聚合特点

  • 松耦合的关系,比组合的松耦合还要送,也可以叫做弱拥有关系
  • 被包含的类可以独立存在,即部分可以脱离整体存在
  • 生命周期独立

依赖关系

除了上面的3中关系外,还有一种依赖关系,那怎么叫做依赖关系呢?相信大家也有到类似的情况,一个类使用另外一个类时仅在函数参数中使用。这种情况明显不属于上面的3种关系,所以这里就有了依赖关系。那都有哪些情况属于依赖关系呢?

  • 函数参数
  • 作为返回类型
  • 在成员函数中以局部变量出现
  • 静态方法调用

具体示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Printer {
public:
void print(Document doc) { //参数依赖
// 使用 Document 对象
}

Report createReport() { // 返回类型依赖
Report report; // 局部变量依赖
return report;
}

void process() {
Logger::log("Processing"); // 静态方法调用依赖
}
};

依赖关系特点

  • 这是一种最弱的关系,关系强度如下:依赖关系<聚合关系<组合关系<继承关系。

设计原则

  • 优先使用组合而非继承
  • 合理使用继承

总结

c++中非常重要的设计模式,就是对上面的几种关系的组合运用。