10_ClassII

面向对象进阶 {对象的生存期、静态成员、友元关系、常对象与常成员、对象数组与对象指针、向量类:vector 、字符串类:string } 静态成员 {为什么要静态、静态数据成员 、静态函数成员 、关键字 static} 友 元 {什么是友元关系、为什么要定义友元、友元函数、友元类、关键字 friend} 常对象与常成员 {为什么需要常对象、常对象的声明、常数据成员、常函数成员、常引用、关键字 const} 对象数组与对象指针 {对象数组的声明与初始化、指向对象的指针、this 指针、指向成员的指针、创建动态对象、特殊符号:-> 、关键字:new、delete} 向量类 vector {向量类,头文件 vector、向量对象、向量操作、关键字 vector} 字符串类 string {字符串对象与字符数组、string 类的构造函数、字符串各种操作、关键字 string}
展开查看详情

1.第十讲 类与对象 ( II ) 面向对象 进阶

2.2 面向对象进阶 对象的生存期 静态成员 友 元关系 常对象与常成员 对象数组与对象指针 向量类 : vector 字符串类: string

3.3 静态生存期:生存期与程序的运行期相同,即一直有效 动态生存期:当对象所在的程序块执行完后即消失 与 普通 变量一样,对象有静态和动态生存期 全局对象:静态生存期 动态对象:动态生存期 对象 的生存期

4.4 类作用域 类作用域:数据成员与局部变量 数据成员可以被类中的所有函数成员访问(类似全局变量) 成员函数中声明的变量是局部变量 如果成员函数中声明了与数据成员 同名 的变量,则数据成员被屏蔽

5.5 例:数据成员作用域 class Point //Point 类的声明 { public: // 外部接口 Point(double a, double b) { x=a; y=b;} void myfun () { cout << x << endl ; int x=10; cout << x ; } private: // 私有数据 int x, y; }; int main() { Point A(4,5 ); A.myfun (); return 0; } ex10_class_01.cpp

6.6 为什么要 静态 静态数据成员 静态函数成员 关键字 static 静态成员

7.7 类的静态成员 静态 数据 成员和 静态函数 成员 一般情况下 ,同一个类的 不同对象分别 有自己的数据成员 ,名字一样,但各自 有值,互不相干 。 但有时希望某些数据 成员为所有对象所共有,这样可以实现数据共享 。 全局变量可以达到共享数据的目的,但其安全性得不到保证:任何函数都可以自由修改全局变量的值,很有可能偶然失误,全局变量的值被错误修改,导致程序的失败。因此在实际工作 中尽量少 使用全局变量。 如果需要在 同一个类的多个对象之间实现数据共享 ,可以使用静态数据成员。

8.8 静态数据成员 用关键字 static 修饰 该类的 所有对象共同使用和维护 该 成员 静态变量可以 初始化 ,但必须 在 类 外部 初始化 静态 数据 成员 class Point { public: ... ... private: int x, y; static int count; // 引用性声明 }; int Point::count=0; // 静态数据成员的定义和初始化 ... ... 例:

9.9 静态数据成员 静态 数据成员 为类的所有对象共有, 不 属于任何特定对象 静态数据成员在 内存中只占一份 空间 只要 在类中定义了静态数据成员,即使不定义对象 , 也 为静态数据成员分配空间,它可以被 引用 如果静态 数据 成员没有初始化,则系统 会自动赋予 初值 0 静态数据成员既可以通过对象名引用,也可以通过类名 来 引用,即: 对象名 . 静态成员名 或 类名 :: 静态成员名 ex10_static_01.cpp

10.10 静态函数成员 用关键字 static 修饰,为 整个类所 共有 调用方式: 类名 :: 静态函数成员名 没有目的对象,所以不能对非静态数据成员进行 默认访问 静态 成员函数一般用于 访问静态数据成员, 维护 对象 之间共享 的数据 静态 函数 成员 class A { public: ... ... static void fun(A a); ... ... }; 例: 实际上 也允许通过对象名调用静态成员 函数,但此时使用的是类的性质,而不是对象本身。 静态成员函数声明时需加 static ,但定义时 不能加 static 。

11.11 静态函数成员 静态 成员 函数可以 直接访问 静态成员,但不能 直接访问 非 静态成员 。 ex10_static_02.cpp // 静态 成员函数中有以下语句: cout << height; // 若 height 是 static ,则合法 cout << width; // 若 width 是非 静态数据成员 ,则不合法 静态 成员 函数访问非静态 数据 成员时,需指明对象 cout << p.width ; // 访问对象 p 的非 静态数据 成员 width 编程好习惯:静态 成员函数只引用静态数据成员 ,逻辑 清楚,不易出错

12.12 友 元 什么是友元关系 为什么要定义友元 友元函数、友元类 关键字 friend

13.13 类的友元 友元提供了一种数据共享的方式,提高了程序效率和可读性 但友元在一定程度上破坏了数据封装和数据隐藏的机制 友元关系: 提供一种不同类或对象的函数成员之间、类的函数成员与一般函数之间进行数据共享的机制 通俗说法:一个类主动声明哪些类或函数是它的朋友,从而给它们提供对本类的访问特许,即可以访问私有成员和保护成员 友元包括: 友元函数 与 友元类 友元类的所有函数成员都是友元函数

14.14 友元函数 用关键字 friend 修饰 可以是普通 函数或其它类 的成员函数 友元函数可以 通过对象 名直接访问 私有成员和保护成员 友元函数 class Point { public: ... ... friend float dist(Point & p1, Point & p2); private: int x, y; }; float dist(Point & p1, Point & p2) { double x=p1.x-p2.x, y=p1.y-p2.y; return sqrt(x*x+y*y); } ... ... 例:

15.15 友元类 用关键字 friend 修饰 友元类的所有函数成员都是友元函数 友元类 class A { public: ... ... friend class B; // 声明 B 是 A 的友元类 ... ... }; 除非确有必要,一般并不把整个类声明为友元类,而只将确实有需要的成员函数声明为友元函数,这样更 安全。

16.16 友元类 关于友元关系的几点说明 友元关系不能传递 友元关系是单向的 友元关系不能被继承 面向对象程序设计的一个基本原则是封装性和信息隐蔽,而友 元是 对封装原则的一个小的破坏。但是它能有助于数据共享 ,提高 程序的 效率。在 使用友元时,要 注意它 的副作用,不要过多地使用友元,只有在使用它能使程序精炼,并能大大提高程序的效率时才用友 元,否则可能得不偿失。

17.17 常对象与常成员 为什么需要常对象 常对象的声明 常数据成员、常函数成员 常引用 关键字 const

18.18 常对象 常对象必须进行 初始化 常对象: 数据成员 均为 常量 将对象声明成 常对象 ,可以有效地保护数据 const 类名 对象 名 ; // OK 类名 const 对象 名 ; // OK 注: 不能通过常对象调用普通成员函数! 常对象只能作为 常成员函数 的目的对象!

19.19 常成员 常对象只能调用常 成员 函数 常成员函数可以被普通对象调用 无论对象是否为常对象 ,常 成员 函数的目的 对象都将被视为常对象 类型说明符 函数名 ( 形参 ) const ; 常成员 函数 常数据成员 将数据成员声明为 常量 必须初始化(采用 参数初始化表 ,不能在构造函数内赋值) // 假定数据成员 a 和 b 是常量, c 是普通变量 Myclass :: Myclass ( int x, int y, int z): a(x ), b(y) { c=z; }

20.20 常成员 class Myclass { ... ... void display() const ; void show(); ... ... const int a ; int b; }; Myclass :: Myclass ( int x, int y ): a(x) { b = y; } ... ... int main () { Myclass obj1(2,3); const Myclass obj2(4,5); Myclass const obj3(6,7 ); obj1.display(); // OK obj2.display(); // OK obj3.display(); // OK obj1.show(); // OK obj2.show (); // ERROR obj3.show (); // ERROR } ex10_class_const.cpp

21.21 常引用 常引用 常引用可以绑定到常 对象,也可以绑定到普通对象 不能通过常引用来修改常引用所绑定的对象 普通 引用 不能绑定到常对象 const 类名 & 引用名; 在 C++ 编程中, 经常用常指针和常引用作函数 参数,这样既可以节省存储量和运算时间,又能 保证 数据的安全。 ex10_ref_const.cpp

22.22 对象数组与对象指针 对象数组的声明与初始化 指向对象的指针、 this 指针 指向成员的指针 创建动态对象 特殊符号: -> 关键字: new 、 delete

23.23 对象数组 一维对象数组的声明 类名 数组名 [n] 一维对象数组的引用 数组名 [k]. 成员名 初始化:对每个元素都调用构造函数 ... .. Point() { x=0; y=0} Point( int a, int b) { x=a; y=b; } ... ... int main() { Point A[2]={ Point(), Point(2,3)}; ... ... 例:

24.24 对象指针 对象指针 :指向对象的指针,存放对象的地址 类名 * 对象指针名 使用对象指针访问对象成员:“ -> ” 对象指针名 -> 成员名 Point a(1,2); Point * pa = &a; 例: 也可以使用普通方式,即: (* 对象指针名 ). 成员名 对象指针的声明 常对象  指向常量的指针 (声明时加 const )

25.25 this 指针 this 指针 : 隐含在 非静态成员函数 中的特殊指针,指向目的对象 this 指针是常指针 当局部作用域中声明了与类成员同名的标识符(如变量名)时,可以通过 this 指针访问该类的成员 当通过一 个 对象的调用成员函数 ( 非静态成员函数 ) 时 ,系统会把该对象的起始地址赋给成员函数 的 this 指针 。 非 静态成员函数 有 this 指针 ,而静态成员函数 没有 this 指针

26.26 例: this 指针 class Point //Point 类的声明 { public: // 外部接口 Point(int a=0, int b=0) { x=a; y=b;} int Getx() {return x;} int Gety() {return y;} int p() {int x=5; cout << x; cout << this->x << endl; } void Setx(int x) { this->x =x; } private: // 私有数据 int x, y; }; ex10_this.cpp

27.27 指向成员的指针 指向成员指针 :直接指向类的成员的指针 指向非静态成员的指针 类型说明符 类名 ::* 指针名 // 指向数据成员 类型说明符 ( 类名 ::* 指针名 )( 参数 ) // 指向函数成员 指向静态成员的指针 对类的静态成员的访问不依赖于对象,可以通过 普通指针 来指向和访问静态成员

28.28 指向非静态成员 函数成员指针的赋值与引用 指针名 = & 类名 :: 函数成员名 ( 对象名 .* 指针名 )( 参数 ) ( 对象指针名 -> * 指针名 )( 参数 ) 数据成员指针的赋值与引用 指针名 = & 类名 :: 数据成员名 对象名 .* 指针名 对象指针名 -> * 指针名

29.29 创建动态对象 动态对象的释放 delete 指针名 类名 * 指针名 =new 类名 () // 不带参数 类名 * 指针名 =new 类名 ( 参数列表 ) // 带参数 程序 结束后,动态 对象也会 被 释放。