nbhkdz.com冰点文库

C++清华大学出版社

时间:2016-03-05


C++语言程序设计

第四章 类与对象
东华理工大学信息工程学院

C++语言程序设计

ECIT CoIE

本章主要内容
?

面向对象的思想

? ? ? ? ?

内联成员函数 拷贝构造函数 类的组合 结构体与联

合体 深度探索
2

?
? ? ? ?

OOP的基本特点
类概念和声明 对象 构造函数 析构函数

C++语言程序设计

ECIT CoIE

回顾:面向过程的设计方法
面 向 对 象 的 思 想
?
? ? ?

重点:
–如何实现的细节和过程,将数据与函数分开。

形式:
–主模块+若干个子模块(main()+子函数)。

特点:
–自顶向下,逐步求精——功能分解。

缺点:
–效率低,程序的可重用性差。

3

C++语言程序设计

ECIT CoIE

面向对象的方法
面 向 对 象 的 思 想
?
? ?

目的:
– 实现软件设计的产业化。

观点:
– 自然界是由实体(对象)所组成。

程序设计方法:
– 使用面向对象的观点来描述模仿并处理 现实问题。

?

要求:
– 高度概括、分类、和抽象。
4

C++语言程序设计

ECIT CoIE

抽象
抽象是对具体对象(问题)进行概括, 抽出这一类对象的公共性质并加以描述 的过程。
– 先注意问题的本质及描述,其次是实现过 程或细节。 – 数据抽象:描述某类对象的属性或状态 (对象相互区别的物理量)。 – 代码抽象:描述某类对象的共有的行为特 征或具有的功能。 – 抽象的实现:通过类的声明。
5

OOP 的 基 本 特 点

C++语言程序设计

ECIT CoIE

抽象实例——钟表
OOP 的 基 本 特 点
?

数据抽象:
int hour,int minute,int second

?

代码抽象:
setTime(),showTime()

6

C++语言程序设计

ECIT CoIE

抽象实例——钟表类
OOP 的 基 本 特 点
class Clock { public: void setTime(int newH, int newM, int newS); void showTime(); private: int hour, minute, second; };

7

C++语言程序设计

ECIT CoIE

抽象实例——人
OOP 的 基 本 特 点
?数据抽象:

string name,string gender,int age,int id
?代码抽象:

生物属性角度: getCloth(), eat(), step(),? 社会属性角度: work(), promote() ,?
8

C++语言程序设计

ECIT CoIE

封装
OOP 的 基 本 特 点
将抽象出的数据成员、代码成员相结 合,将它们视为一个整体。
–目的是曾强安全性和简化编程,使用者 不必了解具体的实现细节,而只需要通 过外部接口,以特定的访问权限,来使 用类的成员。
–实现封装:类声明中的{}
9

C++语言程序设计

ECIT CoIE

封装
OOP 的 基 本 特 点
?

实例:
class Clock { public:void setTime(int newH, int newM, int newS); void showTime(); private: int hour, minute, second; }; 特定的访问权限
外部接口

边界
10

C++语言程序设计

ECIT CoIE

继承与派生
OOP 的 允许程序员在保持原有类特性的基础上, 基 本 进行更具体的说明。 特 实现:声明派生类 —— 见第 7 章 点
是C++中支持层次分类的一种机制,

11

C++语言程序设计

ECIT CoIE

多态性
OOP 的 基 本 特 点
?
?

多态:同一名称,不同的功能实现方式。
目的:达到行为标识统一,减少程序中标 识符的个数。

?

实现:重载函数和虚函数——见第8章

12

C++语言程序设计

ECIT CoIE

c++中的类
类 和 对 象
类是具有相同属性和行为的一组对象 的集合,它为属于该类的全部对象提 供了统一的抽象描述,其内部包括属 性和行为两个主要部分。 ? 利用类可以实现数据的封装、隐藏、 继承与派生。 ? 利用类易于编写大型复杂程序,其模 块化程度比C中采用函数更高。
?
13

C++语言程序设计

ECIT CoIE

类的声明形式
类 类是一种用户自定义类型,声明形式: 和 class 类名称 对 { public: 象 公有成员(外部接口)
private:

私有成员 protected: 保护型成员 }
14

C++语言程序设计

ECIT CoIE

公有类型成员
类 在关键字public后面声明,它们是类 和 对 与外部的接口,任何外部函数都可以访 象 问公有类型数据和函数。

15

C++语言程序设计

ECIT CoIE

私有类型成员
类 在关键字private后面声明,只允许 和 本类中的函数访问,而类外部的任何函 对 数都不能访问。 象
如果紧跟在类名称的后面声明私有成员, 则关键字private可以省略。

16

C++语言程序设计

ECIT CoIE

保护类型
类 和 与private类似,其差别表现在继承与 对 象 派生时对派生类的影响不同,第七章讲。

17

C++语言程序设计

ECIT CoIE

类的成员
类 和 对 象
成员函数 class clock { public: void setTime(int newH, int newM, int newS); void showTime(); private: int hour, hinute, second; };
成员数据
18

void Clock::setTime(int newH, int newM, int newS) { hour = newH; minute = newM; second = newS; } void Clock::showTime() { cout << hour << ":" << minute << ":" << second; }

19

C++语言程序设计

ECIT CoIE

成员数据
类 和 对 象
?

与一般的变量声明相同,但需要将它 放在类的声明体中。

20

C++语言程序设计

ECIT CoIE

成员函数
类 和 对 象
在类中说明原型,可以在类外给出函数 体实现,并在函数名前使用类名加以限 定。也可以直接在类中给出函数体,形 成内联成员函数。 ? 允许声明重载函数和带默认形参值的函 数
?

21

C++语言程序设计

ECIT CoIE

内联成员函数
类 和 对 象
?

为了提高运行时的效率,对于较简单 的函数可以声明为内联形式。
内联函数体中不要有复杂结构(如循 环语句和switch语句)。 在类中声明内联成员函数的方式:
– 将函数体放在类的声明中。 – 使用inline关键字。
22

?

?

C++语言程序设计

ECIT CoIE

内联成员函数举例(一)
类 和 对 象
class Point { public: void init(int initX, int initY) { x = initX; y = initY; } int getX() { return x; } int getY() { return y; } private: int x, y; };

23

C++语言程序设计

ECIT CoIE

内联成员函数举例(二)
类 和 对 象
class Point { public: void init(int initX, int initY); int getX(); int getY(); private: int x, y; };

24

inline void Point:: init(int initX,int initY) { x = initX; y = initY; }
inline int Point::getX() { return x; } inline int Point::GetY() { return y; }

25

C++语言程序设计

ECIT CoIE

对象
类 和 对 象
? ?

类的对象是该类的某一特定实体,即 类类型的变量。 声明形式: 类名 对象名; 例: Clock myClock;

?

26

C++语言程序设计

ECIT CoIE

类中成员的访问方式
类 和 对 象
?

类中成员互访
– 直接使用成员名

?

类外访问
– 使用“对象名.成员名”方式访问 public 属性的成员

27

C++语言程序设计

ECIT CoIE

例4-1类的应用举例
类 和 对 象
#include<iostream> using namespace std; class Clock { ......//类的声明略 } //......类的实现略 int main() { Clock myClock; myClock.setTime(8, 30, 30); myClock.showTime(); return 0; }
28

C++语言程序设计

ECIT CoIE

构造函数
构 造 函 数 和 析 构 函 数
构造函数的作用是在对象被创建时使 用特定的值构造对象,或者说将对象 初始化为一个特定的状态。 ? 在对象创建时由系统自动调用。 ? 如果程序中未声明,则系统自动产生 出一个隐含的参数列表为空的构造函 数 ? 允许为内联函数、重载函数、带默认 形参值的函数
?
29

C++语言程序设计

ECIT CoIE

构造函数举例
构 造 函 数 和 析 构 函 数
class Clock { public: Clock(int newH,int newM,int newS);//构造函数 void setTime(int newH, int newM, int newS); void showTime(); private: int hour, minute, second; };

30

构造函数的实现: Clock::Clock(int newH, int newM, int newS) { hour = newH; minute = newM; second = newS; } 建立对象时构造函数的作用: int main() { Clock c(0,0,0); //隐含调用构造函数,将初始值作为实参。 c.showTime(); return 0; }

31

C++语言程序设计

ECIT CoIE

拷贝构造函数
构 造 函 数 和 析 构 函 数
拷贝构造函数是一种特殊的构造函数,其形参为本 类的对象引用。 class 类名 { public : 类名(形参);//构造函数 类名(类名 &对象名);//拷贝构造函数 ... }; 类名::类(类名 &对象名)//拷贝构造函数的实现 { 函数体 }
32

C++语言程序设计

ECIT CoIE

构 造 函 数 和 析 构 函 数

拷贝构造函数(例4-2)
class Point { public: Point(int xx=0, int yy=0) { x = xx; y = yy; } Point(Point& p); int getX() { return x; } int getY() { return y; } private: int x, y; };

33

Point::Point (Point& p) { x = p.x; y = p.y; cout << "Calling the copy constructor " << endl;

}

34

C++语言程序设计

ECIT CoIE

拷贝构造函数(例4-2)
构 造 函 数 和 析 构 函 数
?

当用类的一个对象去初始化该类的另一 个对象时系统自动调用拷贝构造函数实 现拷贝赋值。
int main() { Point a(1,2);

Point b = a; //拷贝构造函数被调用
cout << b.getX() << endl;

}
35

C++语言程序设计

ECIT CoIE

拷贝构造函数(例4-2)
构 造 函 数 和 析 构 函 数
?

若函数的形参为类对象,调用函数时, 实参赋值给形参,系统自动调用拷贝 构造函数。例如:
void fun1(Point p) { cout << p.getX() << endl; } int main() { Point a(1, 2); fun1(a); //调用拷贝构造函数 return 0; }
36

C++语言程序设计

ECIT CoIE

拷贝构造函数(例4-2)
构 造 函 数 和 析 构 函 数
?

当函数的返回值是类对象时,系统自动调用 拷贝构造函数。例如: Point fun2() { Point a(1, 2); return a; //调用拷贝构造函数 } int main() { Point b; b = fun2(); return 0; }
37

C++语言程序设计

ECIT CoIE

隐含的拷贝构造函数
构 造 函 数 和 析 构 函 数
如果程序员没有为类声明拷贝初始 化构造函数,则编译器自己生成一个隐 含的拷贝构造函数。 这个构造函数执行的功能是:用作 为初始值的对象的每个数据成员的值, 初始化将要建立的对象的对应数据成员。

38

C++语言程序设计

ECIT CoIE

析构函数
构 造 函 数 和 析 构 函 数
? ?

完成对象被删除前的一些清理工作。 在对象的生存期结束的时刻系统自动 调用它,然后再释放此对象所属的空 间。

?

如果程序中未声明析构函数,编译器
将自动产生一个隐含的析构函数。
39

C++语言程序设计

ECIT CoIE

构造函数和析构函数举例
构 造 函 数 和 析 构 函 数
#include <iostream> using namespace std; class Point { public: Point(int xx,int yy); ~Point(); //...其他函数原型 private: int x, y; };
40

Point::Point(int xx,int yy) { x = xx; y = yy; } Point::~Point() { } //...其他函数的实现略

41

C++语言程序设计

ECIT CoIE

类的应用举例(例4-3)
一圆形游泳池如图所示,现在需在其周围 建一圆形过道,并在其四周围上栅栏。栅栏价格 为35元/米,过道造价为20元/平方米。过道宽度 为3米,游泳池半径由键盘输入。要求编程计算 并输出过道和栅栏的造价。
过道
游泳池

42

#include <iostream> using namespace std;
const float PI = 3.141593; //给出p的值 const float FENCE_PRICE = 35; //栅栏的单价 const float CONCRETE_PRICE = 20;// 过道水泥单价 class Circle { //声明定义类Circle 及其数据和方法 public: //外部接口 Circle(float r); //构造函数 float circumference(); //计算圆的周长 float area(); //计算圆的面积 private: //私有数据成员 float radius; //圆半径 };
43

//类的实现
//构造函数初始化数据成员radius Circle::Circle(float r) { radius = r; } //计算圆的周长 float Circle::circumference() { return 2 * PI * radius; } //计算圆的面积 float Circle::area() { return PI * radius * radius; }
44

int main () { float radius; cout << "Enter the radius of the pool: "; // 提示用户输入半径 cin >> radius;
Circle pool(radius); //游泳池边界 Circle poolRim(radius + 3); //栅栏 //计算栅栏造价并输出 float fenceCost = poolRim.circumference() * FENCE_PRICE; cout << "Fencing Cost is $" << fenceCost << endl;
45

//计算过道造价并输出 float concreteCost = (poolRim.area() - pool.area()) * CONCRETE_PRICE; cout << "Concrete Cost is $" << concreteCost << endl;
return 0; } 运行结果 Enter the radius of the pool: 10 Fencing Cost is $2858.85 Concrete Cost is $4335.4

46

C++语言程序设计

ECIT CoIE

组合的概念
类 的 组 合
? ?

类中的成员数据是另一个类的对象。 可以在已有抽象的基础上实现更复杂 的抽象。

47

C++语言程序设计

ECIT CoIE

举例
类 的 组 合
class Point { private: float x, y; //点的坐标 public: Point(float h, float v); //构造函数 float getX(); //取X坐标 float getY(); //取Y坐标 void draw(); //在(x,y)处画点 }; //...函数的实现略
48

class Line { private:

Point p1, p2; //线段的两个端点
public:

Line(Point a, Point b); //构造函数
void draw(void); // 画出线段 };

//...函数的实现略

49

C++语言程序设计

ECIT CoIE

类组合的构造函数设计
类 的 组 合
?

原则:不仅要负责对本类中的基本类型成 员数据赋初值,也要对对象成员初始化。 声明形式:
类名::类名(对象成员所需的形参,本类成员形参) :对象1(参数),对象2(参数),...... { 本类初始化 }

?

50

C++语言程序设计

ECIT CoIE

类组合的构造函数调用
类 的 组 合
?

? ?

构造函数调用顺序:先调用内嵌对象的 构造函数(按内嵌时的声明顺序,先声 明者先构造)。然后调用本类的构造函 数。(析构函数的调用顺序相反) 初始化列表中未出现的内嵌对象,用默 认构造函数(即无形参的)初始化 系统自动生成的隐含的默认构造函数中, 内嵌对象全部用默认构造函数初始化
51

C++语言程序设计

ECIT CoIE

类 的 组 合

类的组合举例(二)
class Part { //部件类 public: Part(); Part(int i); ~Part(); void Print(); private: int val; };
52

class Whole { public: Whole(); Whole(int i, int j, int k); ~Whole(); void Print(); private: Part one; Part two; int date; };
53

Whole::Whole() { date=0; } Whole::Whole(int i, int j, int k) : two(i), one(j), date(k) {} //...其他函数的实现略

54

C++语言程序设计

ECIT CoIE

前向引用声明
类 的 组 合
? ?

类应该先声明,后使用 如果需要在某个类的声明之前,引用 该类,则应进行前向引用声明。 前向引用声明只为程序引入一个标识 符,但具体声明在其他地方。

?

55

C++语言程序设计

ECIT CoIE

前向引用声明举例
类 的 组 合
class B; //前向引用声明 class A { public: void f(B b); }; class B { public: void g(A a); };
56

C++语言程序设计

ECIT CoIE

前向引用声明注意事项
类 的 组 合
?

使用前向引用声明虽然可以解决一些问题,但它 并不是万能的。需要注意的是,尽管使用了前向 引用声明,但是在提供一个完整的类声明之前, 不能声明该类的对象,也不能在内联成员函数中 使用该类的对象。请看下面的程序段: class Fred; //前向引用声明 class Barney { Fred x; //错误:类Fred的声明尚不完善 }; class Fred { Barney y; };
57

C++语言程序设计

ECIT CoIE

前向引用声明注意事项
类 的 组 合
class Fred; //前向引用声明 class Barney { public: ?? void method() { x.yabbaDabbaDo(); //错误:Fred类的对象在定义之前被使用 } private: Fred &x;//正确,经过前向引用声明,可以声明Fred类的对象引用 };

class Fred { public: void yabbaDabbaDo(); private: Barney &y; };

58

C++语言程序设计

ECIT CoIE

前向引用声明注意事项
类 的 组 合
?

应该记住:当你使用前向引用声明时, 你只能使用被声明的符号,而不能涉 及类的任何细节。

59

C++语言程序设计

ECIT CoIE

UML简介
UML 图 形 标 识
UML语言是一种可视化的的面向对象建模语 言。 ? UML有三个基本的部分
?

–事物(Things) UML中重要的组成部分,在模型中属于最静态的 部分,代表概念上的或物理上的元素 –关系(Relationships) 关系把事物紧密联系在一起 –图(Diagrams) 图是很多有相互相关的事物的组
60

C++语言程序设计

ECIT CoIE

UML中有4种类型的事物
UML 图 形 标 识
结构事物(Structural things) ? 动作事物(Behavioral things) ? 分组事物(Grouping things) ? 注释事物(Annotational things)
?

61

C++语言程序设计

ECIT CoIE

UML中的关系
UML 图 形 标 识
依赖(Dependencies) ? 关联(Association) ? 泛化(Generalization) ? 实现(Realization)
?

62

C++语言程序设计

ECIT CoIE

UML中的9种图
UML 图 形 标 识
? ? ? ? ? ? ? ? ?

类图(Class diagram) 对象图(Object diagram) 用例图(Use case diagram) 顺序图(Sequence diagram) 协作图(Collaboration diagram) 状态图(Statechart diagram) 活动图(Activity diagram) 组件图(Component diagram) 实施图(Deployment diagram)
63

C++语言程序设计

ECIT CoIE

类图
UML 图 形 标 识
?

举例:Clock类的完整表示
Clock - hour : int - minute : int - second : int + showTime() : void + setTime(newH:int=0,newM:int=0,newS:int=0):void

?

Clock类的简洁表示
Clock

64

C++语言程序设计

ECIT CoIE

对象图
UML 图 形 标 识
myClock : Clock
- hour : int - minute : int - second : int

myClock : Clock

65

C++语言程序设计

ECIT CoIE

类与对象关系的图形标识
UML 图 形 标 识
?

依赖关系
类 A

类 B

图中的“类A”是源,“类B”是目标,表示 “类A”使用了“类B”,或称“类A”依赖 “类B”

66

C++语言程序设计

ECIT CoIE

类与对象关系的图形标识
UML 图 形 标 识
?

作用关系——关联
重数A 类 A 重数B 类 B

图中的“重数A”决定了类B的每个对象 与类A的多少个对象发生作用,同样“重 数B”决定了类A的每个对象与类B的多少 个对象发生作用。

67

C++语言程序设计

ECIT CoIE

类与对象关系的图形标识
UML 图 形 标 识
?

包含关系——聚集和组合
类 A 重数A 重数B 类 B 类 A 重数A

重数B 类 B

聚集表示类之间的关系是整体与部分的关系, “包含”、“组成”、“分为??部分”等都是 聚集关系。
68

C++语言程序设计

ECIT CoIE

类与对象关系的图形标识
UML 图 形 标 识
?

继承关系——泛化
父类 A 父类 B

子类 1

子类 2

69

C++语言程序设计

ECIT CoIE

注释
UML 图 形 标 识
?

在UML图形上,注释表示为带有褶角 的矩形,然后用虚线连接到UML的其 他元素上,它是一种用于在图中附加 文字注释的机制。
注释文字

70

C++语言程序设计

ECIT CoIE

结构体
结 构 体 与 联 合 体
?

结构体是一种特殊形态的类
– 与类的唯一区别:类的缺省访问权限是 private,结构体的缺省访问权限是public – 结构体存在的主要原因:与C语言保持兼容

?

什么时候用结构体而不用类
– 定义主要用来保存数据、而没有什么操作的 类型 – 人们习惯将结构体的数据成员设为公有,因 此这时用结构体更方便

71

C++语言程序设计

ECIT CoIE

结构体的定义和初始化
结 构 体 与 联 合 体
?

结构体定义
struct 结构体名称 { 公有成员 protected: 保护型成员 private: 私有成员 };

?

一些结构体变量的初始化可以用以下形式
类型名 变量名 = { 成员数据1初值, 成员数据2初 值, …… };
72

C++语言程序设计

ECIT CoIE

结构体举例(例4-7)
结 构 体 与 联 合 体
#include <iostream> #include <iomanip> #include <string> using namespace std; struct Student { int num; string name; 详细介绍 char sex; int age; }; //学生信息结构体 //学号 //姓名,字符串对象,将在第6章 //性别 //年龄

73

C++语言程序设计

ECIT CoIE

结构体举例(例4-7)
结 构 体 与 联 合 体
int main() { Student stu = { 97001, "Lin Lin", 'F', 19 }; cout << "Num: " << stu.num << endl; cout << "Name: " << stu.name << endl; cout << "Sex: " << stu.sex << endl; cout << "Age: " << stu.age << endl; return 0; } 运行结果: Num: 97001 Name: Lin Lin Sex: F Age: 19

74

C++语言程序设计

ECIT CoIE

联合体
结 构 体 与 联 合 体
?

声明形式
union 联合体名称 { 公有成员 protected: 保护型成员 private: 私有成员 };

?

特点:
– 成员共用相同的内存单元 – 任何两个成员不会同时有效

75

C++语言程序设计

ECIT CoIE

联合体的内存分配
结 构 体 与 联 合 体
union Mark { //表示成绩的联合体 char grade; //等级制的成绩 bool pass; //只记是否通过课程的成绩 int percent; //百分制的成绩 }; Mark grade pass percent

76

C++语言程序设计

ECIT CoIE

无名联合
结 构 体 与 联 合 体
无名联合没有标记名,只是声明一个成员项 的集合,这些成员项具有相同的内存地址, 可以由成员项的名字直接访问。 ? 例:
?

union { int i; float f; } 在程序中可以这样使用: i = 10; f = 2.2;
77

C++语言程序设计

ECIT CoIE

联合体举例(例4-8)
结 构 体 与 联 合 体
#include <string> #include <iostream> using namespace std; class ExamInfo { private: string name; //课程名称 enum { GRADE, PASS, PERCENTAGE } mode;// 采用何种计分 方式 union { char grade; //等级制的成绩 bool pass; //只记是否通过课程的成绩 int percent; //百分制的成绩 };

78

C++语言程序设计

ECIT CoIE

联合体举例(例4-8)
结 构 public: //三种构造函数,分别用等级、是否通过和百分初始化 体 ExamInfo(string name, char grade) : name(name), mode(GRADE), grade(grade) { } 与 ExamInfo(string name, bool pass) 联 : name(name), mode(PASS), pass(pass) { } name, int percent) 合 ExamInfo(string : name(name), mode(PERCENTAGE), percent(percent) 体 {}
void show(); }

79

C++语言程序设计

ECIT CoIE

联合体举例(例4-8)
结 构 体 与 联 合 体
void ExamInfo::show() { cout << name << ": "; switch (mode) { case GRADE: cout << grade; break; case PASS: cout << (pass ? "PASS" : "FAIL"); break; case PERCENTAGE: cout << percent; break; } cout << endl; }

80

C++语言程序设计

ECIT CoIE

联合体举例(例4-8)
结 构 体 与 联 合 体
int main() { ExamInfo course1("English", 'B'); ExamInfo course2("Calculus", true); ExamInfo course3("C++ Programming", 85); course1.show(); course2.show(); course3.show(); return 0; } 运行结果: English: B Calculus: PASS C++ Programming: 85

81

C++语言程序设计

ECIT CoIE

位域
?

位域的声明形式
– 数据类型说明符 成员名 : 位数;

深 度 探 索

?

位域的作用
– 通过“打包”,使类的不同成员共享相同的 字节,从而节省存储空间。

?

注意事项
– 具体的打包方式,因编译器而异; – 只有bool、char、int和枚举类型的成员,允 许定义为位域; – 节省空间,但可能增加时间开销。
82

C++语言程序设计

ECIT CoIE

例4-9
?

深 度 探 索

设计一个结构体存储学生的成绩信息, 需要包括学号、年级和成绩三项内容, 学号的范围是0到99,999,999,年级 分为freshman、sophomore、 junior、senior四种,成绩包括A、B、 C、D四个等级。

83

C++语言程序设计

ECIT CoIE

例4-9
#include <iostream> using namespace std;

深 度 探 索

enum Level { FRESHMAN, SOPHOMORE, JUNIOR, SENIOR }; enum Grade { A, B, C, D }; class Student { public: Student(unsigned number, Level level, Grade grade) : number(number), level(level), grade(grade) { } void show(); private: unsigned number : 27; Level level : 2; Grade grade : 2; };

84

C++语言程序设计

ECIT CoIE

例4-9
深 度 探 索
void Student::show() { cout << "Number: " << number << endl; cout << "Level: "; switch (level) { case FRESHMAN: cout << "freshman"; break; case SOPHOMORE: cout << "sophomore"; break; case JUNIOR: cout << "junior"; break; case SENIOR: cout << "senior"; break; } cout << endl; cout << "Grade: "; switch (grade) { case A: cout << "A"; break; case B: cout << "B"; break; case C: cout << "C"; break; case D: cout << "D"; break; } cout << endl; }

85

C++语言程序设计

ECIT CoIE

例4-9
深 度 探 索
int main() { Student s(12345678, SOPHOMORE, B); cout << "Size of Student: " << sizeof(Student) << endl; s.show(); return 0; } 运行结果:(运行结果第一行会因编译环境的不同而有所差异)
Size of Student: 4 Number: 12345678 Level: sophomore Grade: B

86

C++语言程序设计

ECIT CoIE

临时对象与类型转换
深 度 探 索
( 例4-2中Point构造函数:Point(int xx = 0, int yy = 0) ) ? 临时对象的显式创建

– 可以直接调用类的构造函数显式创建临时对象 例:Line x(Point(1, 1), Point(4, 5)); – 临时对象到表达式执行完毕后即销毁
?

单参数构造函数可以设立类型转换
– Point(1)表示创建一个临时对象,同时也表示显式类 型转换 – 与Point(1)等价的形式:
? ?

(Point) 1 static_cast<Point>(1)

– 无论形式为何,执行转换时都会创建临时对象

87

C++语言程序设计

ECIT CoIE

隐含转换
?

深 度 探 索

由构造函数确立的类型转换,可以隐 含执行
–例:Line x(1, 4); –效果:构造以(1,0)和(4,0)两坐标为端 点的线段,这里Point的构造函数被隐含 调用

?

避免隐含转换的发生
– 在构造函数中使用explicit关键字, explicit要写在类定义中的构造函数前
88

C++语言程序设计

ECIT CoIE

例4-10
深 度 探 索
#include <iostream> using namespace std; class Complex { //复数类 private: float real, imag;//复数的实部和虚部 public: //构造函数,可以当作隐式类型转换使用 Complex(float real = 0, float imag = 0) : real(real), imag(imag) { } Complex add(Complex c) { //复数加法,生成临时对象并返回 return Complex(real + c.real, imag + c.imag); } Complex sub(Complex c) { //复数减法,生成临时对象并返回 return Complex(real - c.real, imag - c.imag); } Complex mul(Complex c) { //复数乘法,生成临时对象并返回 return Complex(real * c.real - imag * c.imag, real * c.imag + imag * c.real); }

89

C++语言程序设计

ECIT CoIE

例4-10
深 度 探 索
void show() { //显示复数 if (imag >= 0) cout << real << " + " << imag << 'i' << endl; else cout << real << " - " << -imag << 'i' << endl; } }; int main() { Complex z(1, 2); //z = 1 + 2i z.add(Complex(3, 4)).show(); //Complex(3, 4)是临时对象 static_cast<Complex>(5).sub(z).show(); //输出5 – z,使用了显示类型转换 z.mul(-3.0f).show(); //输出z * (-3),使用了隐含类型转换 return 0; }
运行结果: 4 + 6i 4 - 2i -3 - 6i

90

C++语言程序设计

ECIT CoIE

成员函数的调用
?

成员函数调用的实现机制
– 问题的关键:如何传递调用的目的对象 – 解决办法:把目的对象的引用当作参数传递

深 度 探 索

void Clock::setTime(int newH, int newM, int newS) { hour = newH; minute = newM; second = newS; }

void Clock_setTime(_Clock &_this, int newH, int newM, int newS) { _this.hour = newH; _this.minute = newM; _this.second = newS; }

myClock.setTime(8, 30, 30);

Clock_setTime(myClock, 8, 30, 30);

91

C++语言程序设计

ECIT CoIE

构造函数的调用
深 度 探 索
Line::Line(Point xp1, Point xp2) : p1(xp1), p2(xp2) { double x = p1.getX() - p2.getX(); double y = p1.getY() - p2.getY(); len = sqrt(x * x + y * y); } void Line_Line(_Line &_this, _Point xp1, _Point xp2) { Point_Point(_this.p1, xp1); Point_Point(_this.p2, xp2); double x = Point_getX(_this.p1) Point_getX(_this.p2); double y = Point_getY(_this.p1) Point_getY(_this.p2); _this.len = sqrt(x * x + y * y); } Line line(myp1, myp2);

_Line line; Line_Line(line, myp1, myp2);

先分配空间,再调用构造函数

92

C++语言程序设计

ECIT CoIE

对象作为参数的传递方式
?

对象参数的传递方式
– 通过运行栈来传递 – 主调函数调用拷贝构造函数,在运行栈的传 参区域上创建对象 – 被调函数可以读取传参区域上的对象

深 度 探 索

?

有时对拷贝构造函数的调用可以省去
例: z.add(Complex(3, 4)) – 直接调用构造函数Complex(float, float),在 运行栈的传参区域上建立对象
93

C++语言程序设计

ECIT CoIE

对象作为返回值的传递方式
?

传递方式
– 在主调函数中创建临时对象 – 主调函数把该对象地址(引用)传递给被调函 数 – 被调函数返回时,在该地址上执行拷贝构造
Point fun2() { Point a(1, 2); return a; } void fun2(_Point &result) { _Point a; Point_Point(a, 1, 2); Point_Point(result, a); } _Point temp; fun2(temp); b = temp;
94

深 度 探 索

b = fun2();

C++语言程序设计

ECIT CoIE

对象作为返回值的传递方式
?

有时返回时可以不调用拷贝构造函数
例:return Point(1, 2); – 直接调用构造函数Point(int, int),生成返 回的对象

深 度 探 索

?

有时主调函数中可以不建立临时对象
例:Point p = fun2(); – 先为p申请空间,调用fun2()前传递p的地 址,这样在返回时可直接在p的空间上构 造返回对象
95

C++语言程序设计

ECIT CoIE

小结与复习建议
?

主要内容
– 面向对象的基本概念、类和对象的声明、构造 函数、析构函数、内联成员函数、拷贝构造函 数、类的组合

?

达到的目标
– 学会将一段功能相对独立的程序写成一个函数, 为下一章学习类和对象打好必要的基础。

?

实验任务
– 实验四
96


...答案-第一章--谭浩强-清华大学出版社

C++面向对象程序设计》 答案-第一章--谭浩强-清华大学出版社C++面相对象程序设计》谭浩强-清华大学出版社,第一章答案,有些题目有不同的解法提供参考,十分详细...

...程序设计答案》-第七章--谭浩强-清华大学出版社

C++面向对象程序设计答案》-第七章--谭浩强-清华大学出版社C++面向对象程序设计答案》-第七章--谭浩强-清华大学出版社,有些题目提供了一种以上解法供参考~《...

...对象程序设计教程与实验(第二版)清华大学出版社1—8...

Visual_C++面向对象程序设计教程与实验(第二版)清华大学出版社1—8章答案_理学_高等教育_教育专区。第一章 1. 什么是面向对象程序设计?它与传统的结构化程序设计...

...答案-第四章--谭浩强-清华大学出版社

C++面向对象程序设计》答案-第四章--谭浩强-清华大学出版社_IT/计算机_专业资料。《C++面向对象程序设计》答案-第四章--谭浩强-清华大学出版社,有些题目提供了...

清华大学出版社出版 谭浩强主编 C++程序设计课后相接答...

清华大学出版社出版 谭浩强主编 C++程序设计课后相接答案11章(白永利) 清华大学出版社出版 谭浩强主编 C++程序设计课后相接答案第11章清华大学出版社出版 谭浩强主编...

清华大学出版社出版 谭浩强主编 C++程序设计课后相接答...

清华大学出版社出版 谭浩...1/2 相关文档推荐 清华大学出版社出版 谭浩......例1.1 输出一行字符: "This is a C++ program." . 程序如下: #include ...

...程序设计答案》-第六章--谭浩强-清华大学出版社

C++面向对象程序设计答案》-第六章--谭浩强-清华大学出版社_IT/计算机_专业资料。《C++面向对象程序设计答案》-第六章--谭浩强-清华大学出版社,有些题目提供了...

...第2版 (王育坚) 清华大学出版社 课后答案

Visual C++面向对象编程教程 第2版 (王育坚) 清华大学出版社 课后答案_理学_高等教育_教育专区。Visual C++面向对象编程教程 第2版 (王育坚) 清华大学出版社 课后...

...习题答案-第二章--谭浩强-清华大学出版社

C++面向对象程序设计》习题答案-第二章--谭浩强-清华大学出版社_IT/计算机_专业资料。C++面向对象程序设计答案-第一章--谭浩强-清华大学出版社,有些题目提供了...

c语言程序设计答案(常东超)清华大学出版社

c语言程序设计答案(常东超)清华大学出版社_理学_高等教育_教育专区 暂无评价|0人阅读|0次下载|举报文档 c语言程序设计答案(常东超)清华大学出版社_理学_高等...