1 / 79

第六章 类和对象 ( 二 )

第六章 类和对象 ( 二 ). § 6.1 对象指针和对象引用 § 6.2 数组 § 6.3 常类型 § 6.4 子对象和堆对象 § 6.5 类型转换. § 6.1 对象指针和对象引用. 一、指向类成员的指针. 二、对象指针和对象引用作函数参数. 三、 this 指针. < 对象 > . * < 指针名 >. < 指向对象的指针 > - > * < 指针名 >. 一、指向类成员的指针. 1. 指向 数据成员 的指针. 定义 < 类型说明符 > * < 指针名 > 赋值 < 指针名 > = & < 数据成员名 >. < 类名 > ::.

zona
Download Presentation

第六章 类和对象 ( 二 )

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第六章 类和对象(二) §6.1对象指针和对象引用 §6.2数组 §6.3常类型 §6.4子对象和堆对象 §6.5类型转换

  2. §6.1 对象指针和对象引用 一、指向类成员的指针 二、对象指针和对象引用作函数参数 三、 this指针

  3. <对象>.*<指针名> <指向对象的指针> ->*<指针名> 一、指向类成员的指针 1. 指向数据成员的指针 定义 <类型说明符>*<指针名> 赋值 <指针名> =&<数据成员名> <类名>:: <类名>:: • 使用 通过“对象”来引用指针“指向的成员” 成员指针运算符

  4. (对象.*<指针名>)(<参数表>) (指向对象的指针->*<指针名>)(<参数表>) 一、指向类成员的指针 2. 指向成员函数的指针 定义 <类型>( *<指针名>) (<参数表>) 赋值 <指针名> = <成员函数名> <类名>:: <类名>:: • 引用 成员指针运算符

  5. classA { public: int fun(int b) {return a*c+b:} A(int i) {a=i;} int c; private: int a; }; • 定义一个指向类A的数据成员c的指针pc: • 定义一个指向类A的成员函数fun的指针pfun: int A::*pc= &A::c; int (A::*pfun)(int) = A::fun;

  6. p->fun(5); x.fun(5); x.*pfun(5); 指针pc 指针pfun 指针p classA { public: int fun(int b) {return a*c+b;} A(int i) {a=i;} int c; private: int a; }; //注意*的位置 //注意&的位置 void main( ) { Ax(8); int A::*pc; pc =&A::c; x.*pc = 3; int (A::*pfun)(int); pfun = A::fun; A*p = &x; cout<<( p->*pfun)(5)<<endl; } [例6.1] x.c =3; 29

  7. §6.1 对象指针和对象引用 一、指向类成员的指针 二、对象指针和对象引用作函数参数 三、 this指针

  8. 实现“传址调用”,被调函数中通过改变形参指针所指对象的值来影响实参;实现“传址调用”,被调函数中通过改变形参指针所指对象的值来影响实参; • 只将实参的地址传给形参,不进行副本拷贝, • 减少时空开销,提高运行效率; • 要求 形参:对象指针 • 实参:对象的地址值 二、对象指针和对象引用作函数参数 1.对象指针作函数参数

  9. #include <iostream.h> class M { public: M( ) {x=y=0;} M(int i, int j) {x=i; y=j;} void copy(M*m); void setxy(int i, int j) {x=i; y=j;} void print() { cout<<x<<","<<y<<endl; } private: int x, y; }; [例 6.2] void main( ) { Mp(5,7), q; q.copy(&p); fun(p, &q); p.print( ); q.print( ); } void M::copy(M*m) { x=m->x; y=m->y; } void fun(M m1, M*m2) { m1.setxy(12, 15); m2->setxy(22, 25); } 5, 7 22, 25

  10. 具有对象指针作函数参数的优点,被调函数中通过改变引用的值来直接影响实参;具有对象指针作函数参数的优点,被调函数中通过改变引用的值来直接影响实参; • 函数参数形式更简单、直接 • 要求 形参:对象引用 • 实参:对象 二、对象指针和对象引用作函数参数 2.对象引用作函数参数

  11. #include <iostream.h> class M { public: M( ) {x=y=0;} M(int i, int j) {x=i; y=j;} void copy(M&m); void setxy(int i, int j) {x=i; y=j;} void print() {cout<<x<<","<<y<<endl;} private: int x, y; }; [例 6.3] void main( ) { Mp(5,7), q; q.copy(p); fun(p, q); p.print( ); q.print( ); } void M::copy(M&m) { x=m.x; y=m.y; } void fun(M m1, M&m2) { m1.setxy(12, 15); m2.setxy(22, 25); }

  12. 分析程序运行结果: void Point::fun(Point&p) { X=p.X; Y=p.X; cout<<"fun(Point &p)."<<endl; } #include<iostream.h> classPoint {public: Point(int a, int b) { X=a; Y=b; } void fun(Point&p); void fun(Point *p); private: int X,Y; }; void Point::fun(Point *p) { X=p->X; Y=p->Y; cout<<"fun(Point *p)."<<endl; } void main( ) { Point p1(1, 2), p2(3, 4); p1.fun(p2); }

  13. §6.1 对象指针和对象引用 一、指向类成员的指针 二、对象指针和对象引用作函数参数 三、 this指针

  14. 三、this指针 对象指针 • 隐含于每个类的成员函数中; • 指向正在被成员函数操作的对象; • 对象调用成员函数时,编译器先将该对象的地址赋给this指针,然后调用成员函数; • 调用成员函数存取数据成员时,隐含使用this指针;一般不显示使用this指针引用数据成员。

  15. #include <iostream.h> class A { public: A() {a=b=0;} A(int i, int j) {a=i; b=j;} void copy(A &aa); void print() { cout<<a<<","<<b<<endl; } private: int a, b; }; [例6.4] void A::copy(A&aa) { if( this==&aa ) return; *this=aa; } void A::copy(A &aa) { (*this).a =aa.a; (*this).b =aa.b; } void main( ) { A a1, a2(3, 4); a1.copy(a2); a1.print( ); } 3, 4

  16. #include <iostream.h> class A { public: A() {a=b=0;} A(int i, int j) {a=i; b=j;} void copy(A &aa); void print() { cout<<a<<","<<b<<endl; } private: int a, b; }; [例6.4] void A::copy(A&aa) { if( this==&aa ) return; *this=aa; } void A::copy(A &aa) { (*this).a =aa.a; (*this).b =aa.b; } void main( ) { A a1, a2(3, 4); a1.copy(a2); a1.print( ); } void A::copy(A &aa) { this->a =aa.a; this->b =aa.b; }

  17. #include <iostream.h> class A { public: A() {a=b=0;} A(int i, int j) {a=i; b=j;} void copy(A &aa); void print() { cout<<a<<","<<b<<endl; } private: int a, b; }; [例6.4] void A::copy(A &aa) { (*this).a=aa.a; (*this).b=aa.b; } void A::copy(A&aa) { if( this==&aa ) return; *this=aa; } void A::copy(A &aa) { a =aa.a; b =aa.b; } void main( ) { A a1, a2(3, 4); a1.copy(a2); a1.print( ); } void A::copy(A &aa) { this->a=aa.a; this->b=aa.b; }

  18. 三、this指针 所有的成员函数吗? • 隐含于每个类的成员函数中; • 指向正在被成员函数操作的对象; • 对象调用成员函数时,编译器先将该对象的地址赋给this指针,然后调用成员函数; • 调用成员函数存取数据成员时,隐含使用this指针;一般不显示使用this指针引用数据成员。 • 非静态成员函数有隐含的“this”指针(指向对象); • 静态成员函数没有隐含的“this”指针。因为静态函数属于类,直接操作类中的静态数据成员

  19. §6.2 数 组 一、对象数组 二、指向数组的指针和指针数组

  20. 一、对象数组 • 数组元素是同一个类的若干对象 • 定义 • <类名><数组名>[<大小>]… • 赋值 • 可以被赋初值,也可以被赋值; • 数组元素下标:从0开始;

  21. #include <iostream.h> class DATE { public: DATE( ) {month=day=year=0;} DATE(int m, int d, int y) { month=m; day=d; year=y; } void print( ) { cout<<month<<“/"<<day<<“/"<<year<<endl; } private: int month, day, year; }; [例6.5] void main( ) { DATEdates[5]={ DATE(9, 5, 2002), DATE(9, 6, 2002) }; //赋初值 dates[2]=DATE(9, 7, 2002);//赋值 dates[3]=DATE(9, 8, 2002); dates[4]=DATE(9, 9, 2002); for(int i=0; i<5; i++) dates[i].print( ); //引用 } 9/5/2002 9/6/2002 9/7/2002 9/8/2002 9/9/2002

  22. §6.2 数 组 一、对象数组 二、指向数组的指针和指针数组

  23. 二、指向数组的指针和指针数组 1. 指向数组的指针 • 指向一般数组的指针 • (2) 指向对象数组的指针 <类型说明符> (*<指针名>)[<大小>] 例:int (*pa)[3]; <类名> (*<指针名>) [<大小>]

  24. [例6.6] #include<iostream.h> int a[3][3]={1, 2, 3, 4, 5, 6, 7, 8, 9}; void main( ) { int (*pa)[3](a); for(int i=0; i<3; i++) { for(int j=0; j<3; j++) cout<<*(*(pa+i)+j)<<" "; cout<<"\n"; } } int (*pa)[3] = a; 1 2 3 4 5 6 7 8 9

  25. class M { public: M( ) {a=b=0;} M(int i, int j) {a=i; b=j;} void print() { cout<<a<<","<<b<<'\t'; } private: int a, b; }; [例6.7] void main( ) { Mm[2][4]; //对象数组 int x=10, y=10; for(int i=0; i<2; i++) for(int j=0; j<4; j++) m[i][j]=M(x+=2, y+=10); //赋值 M(*pm)[4](m); //指向对象数组的指针pc for(i=0; i<2; i++) { for(int j=0; j<4; j++) (*(*(pm+i)+j)).print(); cout<<endl; } } M (*pm)[4] =m; 12,20 14,30 16,40 18,50 20,60 22,70 24,80 26,90

  26. 二、指向数组的指针和指针数组 • 指针数组 • 数组元素为指针的数组 (1) 一般的指针数组 (2) 对象指针数组 常用: 字符指针数组 char* str[10]; <类型名> *<数组名>[<大小>]… <类名> *<数组名>[<大小>]… 数组元素:指向同一类对象的指针

  27. classA { public: A(int i=0, int j=0) {a=i; b=j;} void print( ); private: int a, b; }; [例6.9] void A::print( ) { cout<<a<<","<<b<<endl; } void main( ) { Aa1(7, 8), a2, a3(5, 7); A*b[3]={&a3, &a2, &a1}; //对象指针数组 for(int i=0; i<3; i++) b[i]->print( ); } 数组元素:指向A类对象的指针 5, 7 0, 0 7, 8

  28. void A::print( ) { cout<<a<<","<<b<<endl; } void main( ) { A c[3]={ A(7, 8), A(5, 7)}; A* b; b=c; for(int i=0; i<3; i++) (b+i)->print( ); } [例6.9](我的) #include<iostream.h> class A { public: A(int i=0, int j=0) {a=i; b=j;} void print( ); private: int a, b; };

  29. §6.3 常类型 • 经const说明的类型,其值不能更新,定义时必须初始化! 一、一般常量和对象常量 二、常指针和常引用 三、常成员函数 四、常数据成员

  30. 例: constint a[5]={1, 2, 3, 4, 5}; 例: intconst a[5]={1, 2, 3, 4, 5}; 初始化 一、一般常量和对象常量 1. 一般常量 • 简单类型 • 常数组 const<类型> <常量名> = <值> <类型>const <常量名> = <值> 例: constint x=2; 例: int const x=2; 数组元素的值不能更新 const<类型> <数组名>[<大小>]… <类型>const <数组名>[<大小>]…

  31. 一、一般常量和对象常量 • 常对象(对象常量) <类名>const <对象名> const <类名> <对象名> 定义常对象时要初始化, 对象不能被更新 class A { public: A(int i, int j) {x=i; y=j;} private: int x, y; }; 对象a1、a2值不能再被更新 例:constA a1(3, 4); //常对象a1 例:Aconst a2(8,19); //常对象a2

  32. §6.3 常类型 • 经const说明的类型,其值不能更新,定义时必须初始化! 一、一般常量和对象常量 二、常指针和常引用 三、常成员函数 四、常数据成员

  33. 目标 指针常量 1000 不能更改 能更改 目标常量 指针 2000 能更改 不能更改 二、常指针和常引用 1. 常指针 • const修饰指针时,随位置不同,含义不同! <类型>*const<指针名> • 指针常量: • 指向常量的指针: const<类型>* <指针名>

  34. 目标 指针常量 不能更改 能更改 目标常量 指针 3000 能更改 不能更改 二、常指针和常引用 1. 常指针 • const修饰指针时,随位置不同,含义不同! <类型>*const<指针名> • 指针常量: 1000 const<类型> * <指针名> • 指向常量的指针:

  35. *ptr1 指针ptr1 不能更改 能更改 常量*ptr1 ptr2 能更改 不能更改 • 定义一个指向字符串string1的指针常量ptr1: char* const ptr1= string1; 于是:ptr1=string2; (  )但*ptr1=“abc”; ( ) • 定义一个指向字符串常量string1的指针ptr2: const char* ptr2= string1; 于是: *ptr2=“xyz”; ( ) ; 但 ptr2=string2; ( )

  36. 类型适应 一种类型的对象能够用于另一种类型的对象使用的环境 #include<iostream.h> const int N=6; void print(const int *p, int n); void main( ) { int array[N]; for(int i=0; i<N; i++) cin>>array[i]; print(array, N); } void print(const int*p, int n) { cout<<"{"<<*p; for(int i=1; i<n; i++) cout<<","<<*(p+i); cout<<"}"<<endl; } [例6.11] 实参:int型数组 形参:指向整常量的指针 一个能够被更新的变量使用在一个不能被更新的环境中,不破坏类型保护!

  37. 二、常指针和常引用 2. 常引用 • “常引用”所引用对象的值不能被更新! const<类型说明符>&<引用名> = 初值 <类型说明符>const&<引用名> = 初值 • 例: double x(6.6); • const double&v =x; • 则 v=12.3; (  ) 注:常指针和常引用往往用作函数的参数,称“常参数”

  38. ?常成员函数删除const,理解this和常函数 classK { public: K(int i) { k=i;} int setk() const{ return k; } private: int k; }; [例6.12] 常引用作函数参数 int add(constK&g1, constK&g2) { int sum= g1.setk( ) + g2.setk( ); return sum; } void main( ) { K k1(8), k2(17); int s=add(k1, k2); //实参:对象 cout<<s<<endl; } 25

  39. §6.3 常类型 • 经const说明的类型,其值不能更新,定义时必须初始化! 一、一般常量和对象常量 二、常指针和常引用 三、常成员函数 四、常数据成员

  40. 三、常成员函数 • 说明格式: <类型> <函数名>(<参数表>)const; • “const”作函数类型的一部分,函数实现也要带const; • 常成员函数不更新对象的数据成员,也不能调用未经“const”修饰的成员函数; 可以用来操作常对象(常量)

  41. classK { public: K(int i) { k=i;} int setk() const{ return k; } private: int k; }; [例6.12] 常成员函数 常引用 int add(constK&g1, constK&g2) { int sum= g1.setk( ) + g2.setk( ); return sum; } 只有常成员函数操作常引用;非常引用可以操作常函数 void main( ) { K k1(8), k2(17); int s=add(k1, k2); cout<<s<<endl; }

  42. classR { public: R(int r1, int r2) { R1=r1; R2=r2; } void print( ); void print( ) const; private: int R1, R2; }; [例6.13] const可以参与区分函数重载 说明 void R::print( ) { cout<<R1<<";"<<R2<<endl; } void main( ) { R a(5, 4); a.print( ); const R b(20, 52); b.print( ); } 实现 void R::print( )const { cout<<R1<<";"<<R2<<endl; } 操作常对象b

  43. 三、常成员函数 <类型> <函数名>(<参数表>)const; • 强调:只有常成员函数才有资格操作“常对象” • 未经const 说明的成员函数不能操作“常对象”; • 若一个对象说明为“常对象”,则它只能调用常成员函数,不能调用其他成员函数; • 常成员函数不仅可以用于操作“常对象”,还可以操作“一般对象”。

  44. classR { public: R(int r1, int r2) { R1=r1; R2=r2; } // void print( ); void print( ) const; private: int R1, R2; }; [例6.13] 说明 实现 void main( ) { R a(5, 4); a.print( ); const R b(20, 52); b.print( ); } void R::print( )const { cout<<R1<<";"<<R2<<endl; } 允许操作“一般对象” 操作“常对象”

  45. classR { public: R(int r1, int r2) { R1=r1; R2=r2; } void print( ); // void print( ) const; private: int R1, R2; }; [例6.13] void R::print( ) { cout<<R1<<";"<<R2<<endl; } void main( ) { R a(5, 4); a.print( ); const R b(20, 52); b.print( ); } 不允许操作“常对象”

  46. §6.3 常类型 • 经const说明的类型,其值不能更新,定义时必须初始化! 一、一般常量和对象常量 二、常指针和常引用 三、常成员函数 四、常数据成员

  47. 常数据成员的初始化方法 四、常数据成员 • const 类型量在对象定义时必须初始化; • 类体中不允许对所定义的数据成员进行初始化; 通过“成员初始化列表”生成构造函数

  48. class A { public: A(int i); void print( ); constint &r; //常int型引用 private: const int a; //常int型量 staticconst intb; //静态常int型量 }; [例6.14] const int A::b= 10; //静态数据初始化 A::A(int i): a(i), r(a) { } void A::print( ) { cout<<a<<":"<<b<<":"<<r<<endl; } 数据成员初始化列表 void main( ) { A a1(100), a2(0); a1.print( ); a2.print( ); } 100: 10: 100 0 : 10: 0

  49. §6.4 子对象和堆对象 一、子对象(对象成员) • 含义 • 一个类的成员是另一个类的对象; • 初始化 • 在构造函数中通过“成员初始化表”来初始化子对象;

  50. [例6.15] classA { public: A(int i, int j) {A1=i; A2=j;} void print() { cout<<A1<<","<<A2<<endl; } private: int A1, A2; }; void B::print( ) { a.print(); cout<<b<<endl; } classB { public: B(int i, int j, int k): a(i, j) { b=k; } void print(); private: Aa; //子对象 int b; }; 子对象 子对象调用成员函数 void main( ) { B b(6,7, 8); b.print( ); } 6, 7 8

More Related