面向对象绪论

面向对象绪论

Guderian出品

面向对象的基本概念

  • 类 Class
  • 对象 Object

浅显理解:类是抽象的对象,对象是具体的类

概念之间的互用

  • 属性 Attribute == 数据 Data == 状态 State == 信息 Information
  • 操作 Operation == 方法 Method == 行为 Behavior == 职责 Responsibility
  • 对象 Object == 实例 Instance

面向对象的核心特征

  • 封装 Encapsulation
  • 继承 Inheritance
  • 多态 Polymorphism

封装、继承和多态被称为所谓的“面向对象三大特征”

  • 聚合/组合 Aggregation / Composition
  • 接口/实现 Interface / Implementation
  • 抽象 Abstraction

封装 Encapsulation

是指隐藏对象的属性和实现细节,仅对外提供公共访问方式

  1. 封装什么?
  • 内部的、不想让其他人随意了解的信息
  • 类的属性 Attribute
  • 类的方法 Method
  1. 为什么要封装?
  • 保护隐私
  • 保护数据安全
  • 隔离复杂度
  1. 面向对象的封装有四种方式
  • Public
  • Private
  • Protected
  • Package

继承 Inheritance

一个类从其他类获得它的状态和行为,同时还可以加上自己额外的状态和行为

父类中的属性和方法,在子类中可以重复使用,子类就不需要再定义了,这样即可实现代码的可重用性。如以下类图例子,定义类C1Dobject一维物体,它有一个属性x对应x轴上的一个坐标,两个方法getx()setx(int)分别表示x坐标的获取和设置。如果我们需要定义二维物体,就没有必要把x坐标重复定义。我们在类C1Dobject的基础上派生出子类C2Dobject,只需再定义属性y和方法gety()sety(int)就可以完整地抽象出一个二维物体;类似地,如果我们需要定义三维物体,没有必要把x坐标、y坐标重复定义,只需再类C2Dobject的基础上派生出子类C3Dobject,再定义属性z和方法getz()setz(int)即可。显而易见,继承提高了代码的可重用性,减少了创建类的工作量。

以上类图对应的C++代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class C1Dobject
{
private:
int x = 0;
public:
int getx() { return x; }
void setx(int xPrime) { x = xPrime; }
};

class C2Dobject: public C1Dobject
{
private:
int y = 0;
public:
int gety() { return y; }
void sety(int yPrime) { y = yPrime; }
};

class C3Dobject: public C2Dobject
{
private:
int z = 0;
public:
int getz() { return z; }
void setz(int zPrime) { z = zPrime; }
};

多态 Polymorphism

使用指向父类的指针或者引用,能够调用子类的对象

结论:

  1. 当一个类从另一个类继承而来,多态使得子类可以代替父类
  2. 消息发送方不需要知道消息接收方属于哪一个子类
  3. 同一类族的接收者可以按自己的方式处理消息

如以下类图例子,定义形状CShape作为父类,派生出矩形CRectangle和三角形CTriangle。现在假设我们知道一个图形shape,希望获取它的面积,而我们并不需要知道它的具体形状(属于哪一个子类),只需要确保shape所属的类在CShape的类组下即可。图形shape的面积可以通过调用函数area()实现。

C++中多态的实现涉及静态多态动态多态以及虚函数的使用,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>

using namespace std;

class CShape
{
protected:
int width, height;
public:
CShape(int a = 0, int b = 0) { width = a, height = b; }
//纯虚函数,具体功能在子类中实现
virtual int area() = 0;
};

class CRectangle: public CShape
{
public:
//显式调用父类的构造函数
CRectangle( int a = 0, int b = 0): CShape(a, b) {};
int area()
{
cout << "CRectangle area calls: ";
return width * height;
}
};

class CTriangle: public CShape
{
public:
//显式调用父类的构造函数
CTriangle( int a = 0, int b = 0): CShape(a, b) {};
int area()
{
cout << "CTriangle area calls: ";
return width * height / 2;
}
};

int main()
{
CShape *ptr;
CRectangle rect(10, 10);
CTriangle tri(10, 10);

//获取矩形的面积
ptr = &rect;
cout << ptr->area() << endl;

//获取三角形的面积
ptr = &tri;
cout << ptr->area() << endl;

return 0;
}

C++中构成多态需要满足两个条件:

  1. 调用函数的对象须是指针引用
  2. 被调用的函数须是重写 1虚函数 2

聚合/组合 Aggregation / Composition

聚合 Aggregation

A has B,B是A的一部分,但A不控制B的生命周期

如:学校由学生组成,那么学校与学生是聚合关系

UML图中聚合关系的符号如下图

组合 Composition

A has B,B是A的一部分,且A控制B的生命周期

如:树由树叶组成,那么树与树叶是组合关系

UML图中聚合关系的符号如下图

接口/实现 Interface / Implementation

接口 Interface

描述一个类的用户如何与这个类交互

实现 Implementation

完成接口所定义的功能,如类、构建等完成的任务

如电视机、插座、发电厂的关系如何呢?

  • 电视机是用户 client
  • 插座是接口 Interface
  • 发电厂是实现 Implementation

抽象 Abstraction

抽取具体客观事物的共性

抽象是面向对象领域发现类的主要方法

(所谓抽象,玄之又玄,众妙之门)


1. 重写:函数重写必须函数名一致、参数一致、返回值一致
2. 虚函数:在类的成员函数前加virtual关键字

本文标题:面向对象绪论

文章作者:G-SS-Hacker

发布时间:2020年01月28日 - 14:25:40

最后更新:2020年02月22日 - 09:27:15

原始链接:https://G-SS-Hacker.github.io/面向对象绪论/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。