收藏 分享(赏)

C++面向对象程序设计教程.ppt

上传人:j35w19 文档编号:8114556 上传时间:2019-06-09 格式:PPT 页数:94 大小:310KB
下载 相关 举报
C++面向对象程序设计教程.ppt_第1页
第1页 / 共94页
C++面向对象程序设计教程.ppt_第2页
第2页 / 共94页
C++面向对象程序设计教程.ppt_第3页
第3页 / 共94页
C++面向对象程序设计教程.ppt_第4页
第4页 / 共94页
C++面向对象程序设计教程.ppt_第5页
第5页 / 共94页
点击查看更多>>
资源描述

1、C+面向对象程序设计教程,第2章 类和对象,2.1 由结构到类的发展,由结构到类的发展,在C语言中,结构由若干成员组成。在C+中,结构中可以有函数。 类是从结构演变而来的,C+最初称为“带类的C”。从结构到类的演变是从让结构含有函数开始的。,2.1.1 带函数的结构,C+允许程序员在结构中定义函数,这样的函数称为成员函数。原来的结构成员称为数据成员,可使用如下的形式描述结构: struct 结构名 数据成员成员函数 ; 可以像结构变量那样使用成员函数: 结构变量.成员函数(实参),例2.1 在结构中使用成员函数的示例。 struct Point / 数据成员double x; / x坐标dou

2、ble y; / y坐标 / 成员函数 void Set(double a, double b) / 设置坐标 x = a; y = b; void Show() / 显示坐标 cout “(“ x “,“ y “)“ endl; ; int main() / 主函数main() Point v; / 定义变量v.Set(6, 18); / 设置v的坐标v.Show(); / 显示v的坐标(6,18)system(“PAUSE“); / 输出系统提示信息return 0; / 返回值0, 返回操作系统 ,在主函数中的变量通过结构的成员函数操作数据成员,结构Point的成员都可通过变量直接引用,

3、称为具有公有(public)访问权限。面向对象程序设计的封装性包含了隐藏数据成员,可使数据成员具有私有(private) 访问权限实现,这时将不能通过变量直接访问数据成员。,例2.2 使结构具有封装性的示例。 struct Point private: / 数据成员double x; / x坐标double y; / y坐标 public: / 公有函数 void Set(double a, double b) / 设置坐标 x = a; y = b; void Show() / 显示坐标 cout “(“ x “,“ y “)“ endl; ; int main() / 主函数main()

4、Point v; / 定义变量v.Set(6, 18); / 设置v的坐标v.Show(); / 显示v的坐标(6,18)/ cout “(“ v.x “,“ v.y “)“ endl; / 错语,私有成员不能通过变量v直接访问system(“PAUSE“); / 输出系统提示信息return 0; / 返回值0, 返回操作系统 ,没有使用private定义的成员函数,其默认访问权限为public,私有的数据成员必须通过公有的成员函数才能使用,这就成为具有类的性质的结构一般将具有类的性质的结构的变量称为对象。只是类一般使用关键字class定义,类的默认的访问权限是private。,2.1.2

5、用构造函数初始化结构的对象,构造函数用于初始化结构的对象。构造函数名与结构名相同,无返回值类型 对于上面的结构Point,可声明如下的构造函数: Point(double a = 0, double b = 0);,例2.3 使用构造函数初始化对象的示例。 struct Point private: / 数据成员double x; / x坐标double y; / y坐标 public: / 公有函数 Point(double a = 0, double b = 0) / 构造函数 x = a; y = b; void Set(double a, double b) / 设置坐标 x = a;

6、 y = b; void Show() / 显示坐标 cout “(“ x “,“ y “)“ endl; ; int main() / 主函数main() Point v(6, 18); / 定义对象, 构造函数的参数为a=6, b=18v.Show(); / 显示v的坐标(6,18)system(“PAUSE“); / 调用库函数system( ),输出系统提示信息return 0; / 返回值0, 返回操作系统 ,在例2.3中,用关键字class替换struct,这时就得到一个标准的类。 例2.4 标准的类示例。 class Point private: / 数据成员double x;

7、/ x坐标double y; / y坐标 public: / 公有函数 Point(double a = 0, double b = 0)/ 构造函数 x = a; y = b; void Set(double a, double b) / 设置坐标 x = a; y = b; void Show() / 显示坐标 cout “(“ x “,“ y “)“ endl; ; int main() / 主函数main() Point v(6, 18); / 定义对象v.Show(); / 显示v的坐标(6,18)system(“PAUSE“); / 调用库函数system( ),输出系统提示信息r

8、eturn 0; / 返回值0, 返回操作系统 ,2.1.3 从结构到类的演化,2.2 面向对象程序设计技术,面向对象程序设计技术,面向对象的程序设计方法的关键要素: 抽象 封装 继承 多态性,2.2.1 对象,现实世界中客观事物都可以称为对象 例如平面上的点是一个对象,平面上的点的坐标表示了点的属性;设置点的坐标与显示点的坐标是对点的操作,C+语言使用对象名、属性和操作三个要素来描述对象 对象名用于标识一个具体对象;对象的属性用数据来表示,一个属性的值就是描述对象的一个数据;一个操作就是一个函数(使用函数实现操作),这些操作也称为方法或服务。数据称为数据成员,函数称为成员函数,2.2.2 抽

9、象和类,抽象指抽取出事物的本质特征,面向对象程序设计提倡程序员以抽象的观点分析程序,将程序看成是由一组抽象的对象所组成的 可以将一组对象的共同特征抽象出来,从而形成“类”的概念 一个对象是由一些属性和操作构成的。对象的属性描述了对象的内部细节 类是具有相同属性和操作的一组对象的集合,它为属于该类的所有对象提供统一的抽象描述,2.2.3 封装,例如电视机将各种部件都装在机箱里,这就是封装 按照面向程序设计的观点,对象的属性只能由这个对象的操作来存取 封装就是把对象的属性和操作结合成一个独立的系统单位,并尽可能隐蔽对象的内部细节 在类中,封装是通过访问权限实现,如将每个类的属性设置为私有属性,将操

10、作分为私有和公有两种类型。在对象的外部只能访问对象的公有操作,不能直接访问对象的私有部分,2.2.4 继承,继承是指一个对象可以获得另一个对象的特性的机制 比如认识了轮船的特征之后,由于客轮是轮船的特殊种类,因此客轮具有轮船的特征。当研究客轮时,只需专注于发现和描述客轮独有的那些特征即可,2.2.5 多态性,不同的对象调用相同名称的函数,可以导致完全不同的行为的现象称为多态性 利用多态性,程序员只须进行一般形式的函数调用,函数的实现细节由接受函数调用的函数体确定,这样提高了解决复杂问题的能力,2.3 C+类的声明与对象的定义,2.3.1 类的声明,类是一种用户自己构造的数据类型,类要先声明后使

11、 用,在C+中声明类的一般形式为: class 类名 private:私有数据成员和成员函数 protected:保护数据成员和成员函数 public:公有数据成员和成员函数 ;,类中定义的数据和函数称为这个类的成员。类成员具有访问权限,访问权限通过在类成员前面的关键字来定义。关键字private、protected和public代表访问权限分别是私有、保护和公有访问权限,其后定义的成员分别称为私有成员、保护成员和公有成员。访问权限用于控制对象的某个成员在程序中的可访问性,类的上述成员的访问权限遵守如下的访问规则: (1)公有成员:类成员函数以及该类外对象都能够引用这些公有成员。 (2)私有成

12、员:私有成员只能被类成员函数所访问,而不能被该类外的对象直接访问。 (3)保护成员:保护成员只能被该类及其派生类的成员函数所访问,不能被该类外及派生类的对象所直接访问。,例2.5 使用类访问权限的示例。 class Point private: / 私有成员double x; / x坐标 protected: / 保护成员double y; / y坐标 public: / 公有成员 Point(double a = 0, double b = 0) / 构造函数 x = a; y = b; void Set(double a, double b) / 设置坐标 x = a; y = b; vo

13、id Show() / 显示坐标 cout “(“ x “,“ y “)“ endl; ; int main() / 主函数main() Point v(6, 18); / 定义对象 / v.x = 9; / 错, 私有成员不能通过类外的对象直接访问 / v.y = 9; / 错, 保护成员不能通过类外的对象直接访问v.Show(); / 显示v的坐标(6,18)system(“PAUSE“); / 调用库函数system( ),输出系统提示信息return 0; / 返回值0, 返回操作系统 ,2.3.2 在类体外定义成员函数,前面例题中类的成员函数都是在类体中定义的,也可在类体中声明成员函

14、数,在类体外定义成员函数,在类体外定义成员函数的一般形式为: 返回值类型 类名:成员函数名(形参表) 成员函数的函数体 其中“:”是作用域运算符。,例2.6 在类体外定义成员函数的示例。 class Point private: / 数据成员double x; / x坐标double y; / y坐标 public: / 公有函数 Point(double a = 0, double b = 0); / 构造函数void Set(double a, double b); / 设置坐标void Show(); / 显示坐标 ; Point:Point(double a, double b) /

15、构造函数 x = a; y = b; void Point:Set(double a, double b) / 设置坐标 x = a; y = b; void Point:Show() / 显示坐标 cout “(“ x “,“ y “)“ endl; int main() / 主函数main() Point v(6, 18); / 定义对象v.Show(); / 显示v的坐标(6,18)system(“PAUSE“); / 调用库函数system( ),输出系统提示信息return 0; / 返回值0, 返回操作系统 ,2.3.3 定义对象的方法,应先声明类类型,然后再定义对象,例如: Po

16、int v; / 定义对象 在C+中,在声明了类类型后,定义对象有如下两种形式: (1) class 类名 对象名例如class Point v;把class和Point合起来作为一个类型名,用来定义对象,这是从C语言继承下来的,这种形式使用得较少。 (2) 类名 对象名例如Point v;直接用类名定义对象。这种方法方法更为简捷方便,更实用。,例2.7 定义对象不同方法示例。 class Point private: / 数据成员double x; / x坐标double y; / y坐标 public: / 公有成员 Point(double a = 0, double b = 0) /

17、构造函数 x = a; y = b; void Set(double a, double b) / 设置坐标 x = a; y = b; void Show() / 显示坐标 cout “(“ x “,“ y “)“ endl; ; int main() / 主函数main() class Point u(6, 18); / 定义对象u.Show(); / 显示u的坐标(6,18)Point v; / 定义对象v.Set(1, 6); / 设置坐标值(1,6)v.Show(); / 显示v的坐标system(“PAUSE“); / 输出系统提示信息return 0; / 返回值0, 返回操作系

18、统 ,2.3.4 对象成员的引用,通过对象引用对象成员 对象名.成员名 例如: Point u(6, 18); / 定义对象 u.Show(); / 通过对象引用对象的成员 通过指向对象的指针引用对象成员 指向对象的指针-成员名 例如: Point u(6, 8); / 定义对象 Point *p = / 通过指向对象的指针引用对象的成员,例2.8 对象成员的引用示例。 class Point private: / 数据成员double x; / x坐标double y; / y坐标 public: / 公有成员 Point(double a = 0, double b = 0) / 构造函数

19、 x = a; y = b; void Set(double a, double b) / 设置坐标 x = a; y = b; void Show() / 显示坐标 cout Show(); / 通过指针引用对象成员(6,18)system(“PAUSE“); / 输出系统提示信息return 0; / 返回值0, 返回操作系统 ,2.4 构造函数,构造函数,在建立一个对象时,需要对数据成员赋初值 为解决这个问题,C+提供了构造函数来解决对象的初始化问题。构造函数是一种特殊类型的成员函数,构造函数不需要用户来调用它,是在建立对象时自动执行的,2.4.1 构造函数的定义,构造函数的名字与类名同

20、名,没有返回值类型,构造函数的声明格式如下:类名(类型1 形参1,类型2 形参2,); 用户不能调用构造函数,所以不能采用调用函数的方法给出实参。实参是在定义对象时给出的。定义对象的一般格式为:类名 对象名(实参1,实参2,); 如果没有参数,则可采用如下方式定义对象:类名 对象名;,例2.9 构造函数示例。 class Time private: / 数据成员int hour; / 时int minute; / 分int second; / 秒 public: / 公有成员 Time() / 无参构造函数 hour = 0; minute = 0; second = 0; Time(int

21、h, int m, int s) / 带参数的构造函数 hour = h; minute = m; second = s; void Set(int h, int m, int s) / 设置时间 hour = h; minute = m; second = s; void Show() / 显示时间 cout hour “:“ minute “:“ second endl; ; ,例2.9 构造函数示例。 int main() / 主函数main() Time t1; / 调用无参构造函数构造对象t1t1.Show(); / 显示时间0:0:0t1.Set(6, 18, 16); / 设置时

22、间t1.Show(); / 显示时间6:18:16Time t2(12, 16, 19); / 调用带参数的构造函数构造对象t2t2.Show(); / 显示时间12:16:19system(“PAUSE“); / 输出系统提示信息return 0; / 返回值0, 返回操作系统 ,默认构造函数,如在类中没有定义构造函数,则C+会自动生成一个构造函数,只是这个构造函数的函数体是空的,也没有参数,不执行初始化操作,这样的构造函数称为默认构造函数,具体形如下:类名() 一旦用户定义了任何构造函数,系统就不再提供默认构造函数,2.4.2 用参数初始化表对数据成员进行初始化和使用默认参数,在前面关于类

23、的程序中,构造函数是在函数体内通过赋值语句对数据成员实现初始化。C+还提供一种通过参数初始化表来实现对数据成员进行初始化的方法。参数初始化表的形式如下:数据成员1(表达式1), 数据成员2(表达式2), 通过参数初始化表来实现对数据成员进行初始化的方法是在函数首部实现。是在原来函数首部的末尾加一个冒号,然后列出参数的初始化表,有了初始化表,构造函数的函数体一般为空类名(类型1 形参1,类型2 形参2,): 数据成员1(参数表1), 数据成员2(参数表2), 构造函数的参数不但可采用实参来传递,还可指定形参的默认值,如果用户不指定实参值,系统将使用形参的默认值,例2.10 用参数初始化表对数据成

24、员进行初始化的方式示例。 class Time private: / 数据成员int hour; / 时int minute; / 分int second; / 秒 public: / 公有成员 Time(int h = 0, int m = 0, int s = 0): hour(h), minute(m),second(s) / 构造函数void Set(int h, int m, int s) / 设置时间 hour = h; minute = m; second = s; void Show() / 显示时间 cout hour “:“ minute “:“ second endl;

25、; ,例2.10 用参数初始化表对数据成员进行初始化的方式示例。 int main() / 主函数main() Time t1; / 构造函数的参数都采用默认值t1.Show(); / 显示时间0:0:0t1.Set(6, 18, 16); / 设置时间t1.Show(); / 显示时间6:18:16Time t2(12, 16, 19); / 构造函数的参数都采用指定值t2.Show(); / 显示时间12:16:19system(“PAUSE“); / 输出系统提示信息return 0; / 返回值0, 返回操作系统 构造函数中采用参数初始化表,这种方式使用更方便,建议读者在编程时尽量多使

26、用这种方法初始化所有数据成员。,2.5 析构函数,析构函数,析构函数的作用与构造函数相反,它的函数名是“类名”。当对象的生命期结束时,将自动执行析构函数 析构函数没有返回值类型,也没有函数参数。一个类可以有多个构造函数,但是只能有一个析构函数。析构函数的声明格式如下:类名();,例2.11 包含构造函数与析构函数的程序。 class MyClass private: / 数据成员int tag; / 用于标识对象 public: / 公有成员 MyClass(int n = 0): tag(n) / 构造函数MyClass() cout tag “:“ “执行析构函数“ endl; ; int

27、 main() / 主函数main() MyClass a; / 定义对象a, a的数据成员的值为0MyClass *p = new MyClass(1); / 定义指针并分配动态存储空间MyClass *q = new MyClass(2); / 定义指针并分配动态存储空间 delete p; / 释放动态对象,将执行析构函数system(“PAUSE“); / 输出系统提示信息return 0; / 返回值0, 返回操作系统 ,程序运行时屏幕输出如下: 1:执行析构函数! 请按任意键继续. . . 用户按任意键后,屏幕输出如下: 1:执行析构函数 请按任意键继续. . . 0:执行析构函数

28、,2.6 构造函数和析构函数的一般执行顺序,构造函数和析构函数的一般执行顺序,在一个函数中,构造函数的调用顺序是定义对象的顺序,调用析构函数的次序正好与调用构造函数的次序相反 最先被调用的构造函数,其对应的析构函数最后被调用,例2.12 演示构造函数与析构函数执行顺序的程序。 class MyClass private: / 数据成员int tag; / 用于标识对象 public: / 公有成员 MyClass(int n = 0): tag(n) cout tag “:“ “构造函数“ endl; / 构造函数MyClass() cout tag “:“ “析构函数“ endl; / 析构

29、函数 ; int main() / 主函数main() MyClass a; / 定义对象a, a的数据成员的值为0MyClass b(1); / 定义对象b, b的数据成员的值为1MyClass c(2); / 定义对象c, c的数据成员的值为2system(“PAUSE“); / 输出系统提示信息return 0; / 返回值0, 返回操作系统 ,程序运行时屏幕输出如下: 0:构造函数 1:构造函数 2:构造函数 请按任意键继续. . . 2:析构函数 1:析构函数 0:析构函数,动态对象的构造函数与析构函数执行顺序,用new分配动态对象时将自动调用构造函数,只有执行delete释放动态对

30、象时才执行析构函数,也就是析构函数的执行顺序与delete运算符的执行顺序相同,例2.13 动态对象的构造函数与析构函数执行顺序的示例。 class MyClass private: / 数据成员int tag; / 用于标识对象 public: / 公有成员 MyClass(int n = 0): tag(n) cout tag “:“ “构造函数“ endl; / 构造函数MyClass() cout tag “:“ “析构函数“ endl; / 析构函数 ; int main() / 主函数main() MyClass *p = new MyClass; / 定义指针并分配动态存储空间M

31、yClass *q = new MyClass(1); / 定义指针并分配动态存储空间MyClass *r = new MyClass(2); / 定义指针并分配动态存储空间 delete p; / 释放p所指向的动态对象 delete r; / 释放r所指向的动态对象 delete q; / 释放q所指向的动态对象 system(“PAUSE“); / 输出系统提示信息return 0; / 返回值0, 返回操作系统 ,程序运行时屏幕输出如下: 0:构造函数 1:构造函数 2:构造函数 0:析构函数 2:析构函数 1:析构函数 请按任意键继续. . .,2.7 复制构造函数,复制构造函数,复

32、制构造函数利用一个对象初始化另一个对象,复制构造函数形参是被声明为接受对象的引用,为提高程序的安全性,通常声明为常引用。复制构造函数声明如下:类名(const 类名 如没有定义复制构造函数,编译器将提供一个默认复制构造函数,它采用的是将源对象的所有数据成员的值逐一赋值给目标对象的相应的数据成员,例2.14 使用默认复制构造函数的示例。 class Time private: / 数据成员int hour; / 时int minute; / 分int second; / 秒 public: / 公有成员 Time(int h = 0, int m = 0, int s = 0): hour(h)

33、, minute(m), second(s) / 构造函数void Set(int h, int m, int s) / 设置时间 hour = h; minute = m; second = s; void Show() / 显示时间 cout hour “:“ minute “:“ second endl; ; int main() / 主函数main() Time t1(6, 16, 18); / 构造函数的参数都采用默认值t1.Show(); / 显示时间6:16:18Time t2(t1); / 利用默认构造函数构造对象t2t2.Show(); / 显示时间6:16:18system

34、(“PAUSE“); / 输出系统提示信息return 0; / 返回值0, 返回操作系统 ,使用默认复制构造函数可能出现运行时错误,默认复制构造函数只简单地将源对象的数据成员的值赋值给目的对象的相应数据成员 当一个类中包含指针类型的数据成员,并且通过指针在构造函数中动态申请了存储空间,在析构函数中通过指针释放了动态存储空间,这种情况下默认复制构造函数将会出现运行时错误,例2.15 使用默认复制构造函数出现运行时错误的示例。 class String private: / 数据成员char *strValue; / 串值 public: / 公有成员 String(char *s = “) /

35、 构造函数if (s = NULL) s = “; / 将空指针转化为空串strValue = new charstrlen(s) + 1; / 分配存储空间strcpy(strValue, s); / 复制串值String() delete strValue; / 析构函数void Show() cout strValue endl; / 显示串; int main() / 主函数main() String s1(“test“); / 调用普通构造函数的生成对象s1String s2(s1); / 调用默认复制构造函数的生成对象s2s1.Show(); / 显示串s1s2.Show(); /

36、 显示串s2system(“PAUSE“); / 输出系统提示信息return 0; / 返回值0, 返回操作系统 ,程序运行时屏幕输出如下: test test 请按任意键继续. . . 当用户按任一键时,屏幕将会显示类似 Debug Assertion Failed! 的错误 在Dev-C+和MinGW Developer Studio 环境中没有出上述错误现象,原因是在发 现delete释放一个已释放的空间时,不再 作释放操作,也不作异常处理,在执行“String s1(“test“);”语句时,构造函数动态地分配存储空间,并将返回的地址赋给对象s1的成员格拉strValue,然后把“T

37、est”拷贝到这块空间中执行语句“String s2(s1);”时,系统将调用默认的复制构造函数,负责将对象s1的数据成员strValue中存放的地址值赋值给对象s2的数据成员strValue当遇到对象的生命期结束需要撤销对象时,首先由s2对象调用析构函数,将strValue成员所指向的字符串“Test”所在的动态空间释放在对象s1自动调用析构函数之前,对象s1的数据成员strValue指向已释放的内存空间,因此在s1调用析构函数时,无法正确执行析构函数代码“delete strValue”,从而导致出错,定义复制构造函数解决动态内存的问题,定义复制构造函数,通过复制指针数据成员strValu

38、e所指向的动态空间中的内容。这样,两个对象的指针成员strValue就拥有不同的地址值,指向不同的动态存储空间,但两个动态空间中的内容完全一样。,例2.16 定义复制构造函数避免例2.15使用默认构造函数的副作用。 class String private: / 数据成员char *strValue; / 串值 public: / 公有成员 String(char *s = “) / 构造函数if (s = NULL) s = “; / 将空指针转化为空串strValue = new charstrlen(s) + 1;/ 分配存储空间strcpy(strValue, s); / 复制串值St

39、ring(const String / 显示串s2 ,程序运行时屏幕输出如下: test test 请按任意键继续. . .,2.8 用const保护数据,用const保护数据,C+虽然提供了不少有效的措施增加数据的安全性,但是有些数据却可以通过不同方式进行访问,例如形参为变量的引用名,实参为变量名。有时无意之中的误操作会改变有关数据,既要使数据能在一定范围内共享,又要保证它不被任意修改,这时可以使用const,即把有关的数据定义为常量。,2.8.1 常对象成员,常对象成员包括 常数据成员 常成员函数 用户可在声明类时将成员声明为const,常数据成员,常数据成员的值是不能改变的。用关键字co

40、nst来声明常数据成员。常数据成员只能通过构造函数的参数初始化表进行初始化。,例2.17 常数据成员使用示例。 class Circle private: / 数据成员double radius; / 半径const double PI; / 圆周率,常数据成员 public: / 公有成员 Circle(double r): radius(r), PI(3.1415926) / 构造函数void SetRadius(double r) radius = r; / 设置半径void Show() / 输出信息 cout “半径:“ radius “t“; / 输出半径cout “面积:“ PI

41、 * radius * radius endl;/ 输出面积 ; int main() / 主函数main() Circle c(1); / 定义半径为1的圆c.Show(); / 输出圆信息c.SetRadius(2); / 设置圆半径为2c.Show(); / 输出圆信息system(“PAUSE“); / 输出系统提示信息return 0; / 返回值0, 返回操作系统 ,程序运行时屏幕输出如下: 半径:1 面积:3.14159 半径:2 面积:12.5664 请按任意键继续. . .,常成员函数,如果将成员函数声明为常成员函数,则只能引用本类中的数据成员,而不能修改它们,例如只用于输出

42、数据。在声明函数和定义函数时都要有const关键字,在调用时不加const。,例2.18 常数据成员与常成员函数示例示例。 class Circle private: / 数据成员double radius; / 半径const double PI; / 圆周率, 常数据成员 public: / 公有成员 Circle(double r): radius(r), PI(3.1415926) / 构造函数void SetRadius(double r) radius = r; / 设置半径double GetArea() const return PI * radius * radius; /

43、返回面积 void Show() const; / 输出信息 ; void Circle:Show() const / 输出信息 cout “半径:“ radius “t“; / 输出半径cout “面积:“ GetArea() endl; / 输出面积 int main() / 主函数main() Circle c(1); / 定义半径为1的圆c.Show(); / 输出圆信息c.SetRadius(2); / 设置圆半径为2c.Show(); / 输出圆信息 ,程序运行时屏幕输出如下: 半径:1 面积:3.14159 半径:2 面积:12.5664 请按任意键继续. . .,如果将成员函数

44、GetArea()改为非常成员函数,则将会出现编译时错误,这是因为常成员函数Show()的函数体中只能调用常成员函数GetArea(),2.8.2 常对象,在定义对象时可用const指定对象为常对象。不能改变常对象中的数据成员的值,定义常对象的一般形式为: 类名const 对象名; 类名const 对象名(实参表); 也可以把const写在最左面: const类名 对象名; const类名 对象名(实参表); 常对象只能调用常成员函数,非常对象既可以调用非常成员函数,也可以调用常成员函数。,例2.19 常对象示例。 class Circle private: / 数据成员double radi

45、us; / 半径const double PI; / 圆周率, 常数据成员 public: / 公有成员 Circle(double r): radius(r), PI(3.1415926) / 构造函数void SetRadius(double r) radius = r; / 设置半径double GetArea() const return PI * radius * radius; / 返回面积void Show(); / 输出信息void Show() const; / 输出信息 ; void Circle:Show() / 输出信息, 非常成员函数 void Circle:Show

46、() const / 输出信息 int main() / 主函数main() Circle c1(1); / 定义半径为1的圆c1.Show(); / 输出圆信息,调用非常成员函数const Circle c2(2); / 定义半径为2的圆常对象c2.Show(); / 输出圆信息,调用常成员函数 ,程序运行时屏幕输出如下: 非常成员函数:半径:1 面积:3.14159 常成员函数:半径:2 面积:12.5664 请按任意键继续. . .,函数名与形参表完全相同的常成员函数与非常成员函数可以进行重载,非常对象优先调用非常成员函数。,mutable,有时在编程时有要求,一定要修改常对象中的某个数

47、据成员的值,或常成员函数一定要修改某个数据成员的值,例如类中有一个用于计数的变量count,其值应当能不断变化,ANSI C+对此作了特殊的处理,对该数据成员声明为mutable,如mutable int count; 把count声明为易可变的数据成员,这样即使是常对象,常成员函数也以修改它的值。,例2.20 使用mutable的程序示例。 class MyTest private: / 数据成员mutable int count; / 用于计数 public: / 公有成员 MyTest(): count(0) / 构造函数void Show() const / 输出信息, 常成员函数 c

48、out“第“+count“调用void Show() const函数“endl; ; int main() / 主函数main() MyTest a; / 定义非常对象acout “非常对象a:“ endl;a.Show(); / 第1次调用a.Show()a.Show(); / 第2次调用a.Show()const MyTest b; / 定义常对象bcout endl “常对象b:“ endl;b.Show(); / 第1次调用b.Show()b.Show(); / 第2次调用b.Show()system(“PAUSE“); / 输出系统提示信息return 0; / 返回值0, 返回操作系统 ,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报