Upload
zona
View
220
Download
4
Embed Size (px)
DESCRIPTION
第六章 类和对象 ( 二 ). § 6.1 对象指针和对象引用 § 6.2 数组 § 6.3 常类型 § 6.4 子对象和堆对象 § 6.5 类型转换. § 6.1 对象指针和对象引用. 一、指向类成员的指针. 二、对象指针和对象引用作函数参数. 三、 this 指针. < 对象 > . * < 指针名 >. < 指向对象的指针 > - > * < 指针名 >. 一、指向类成员的指针. 1. 指向 数据成员 的指针. 定义 < 类型说明符 > * < 指针名 > 赋值 < 指针名 > = & < 数据成员名 >. < 类名 > ::. - PowerPoint PPT Presentation
Citation preview
第六章 类和对象第六章 类和对象 (( 二二 ))
§§6.16.1 对象指针和对象引用对象指针和对象引用§§6.26.2 数组§§6.36.3 常类型§§6.46.4 子对象和堆对象§§6.56.5 类型转换
§§6.1 6.1 对象指针和对象引对象指针和对象引用用一、指向类成员的指针二、对象指针和对象引用作函数参数三、 this 指针
一、指向类成员的指针一、指向类成员的指针
1) 定义 < 类型说明符 > *< 指针名 >2) 赋值 < 指针名 > = & < 数据成员名 >
< 对象 >.*< 指针名 >< 指向对象的指针 > ->*< 指针名 >
1. 指向数据成员的指针
通过“对象”来引用指针“指向的成员” 成员指针运算符
< 类名 >::
3) 使用< 类名 >::
1) 定义 < 类型 > ( *< 指针名 >) (< 参数表
>)
2) 赋值 < 指针名 > = < 成员函数名 >
( 对象 .*< 指针名 >)(< 参数表 >)( 指向对象的指针 ->*< 指针名 >)(< 参数表>)
一、指向类成员的指针一、指向类成员的指针 2. 指向成员函数的指针
< 类名 >::
< 类名 >::
3) 引用 成员指针运算符
class A{ public: int fun(int b) {return a*c+b:} A(int i) {a=i;} int c; private: int a;};
1) 定义一个指向类 A 的数据成员 c 的指针 pc:
2) 定义一个指向类 A 的成员函数 fun 的指针 pfun:
int A::*pc = & A::c;
int (A::*pfun)(int) = A::fun;
[ 例 6.1]void main( ){ A x(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;
}
p->fun(5); x.fun(5);
x.*pfun(5);
x.c =3;
29
class A{ public: int fun(int b) {return a*c+b;} A(int i) {a=i;} int c; private: int a;};
// 注意 * 的位置// 注意 & 的位置
指针 pc
指针 pfun
指针 p
一、指向类成员的指针二、对象指针和对象引用作函数参数三、 this 指针
§§6.1 6.1 对象指针和对象引用对象指针和对象引用
二、对象指针和对象引用作函数参数
1) 实现“传址调用”,被调函数中通过改变形参指针所指对象的值来影响实参;2) 只将实参的地址传给形参,不进行副本拷贝, 减少时空开销,提高运行效率;3) 要求 形参:对象指针 实参:对象的地址值
1. 对象指针作函数参数
[ 例 6.2] #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;};
void main( ){ M p(5,7), q; q.copy(&p); fun(p, &q); p.print( ); q.print( ); }
5, 722, 25
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);}
1) 具有对象指针作函数参数的优点,被调函数中通过改变引用的值来直接影响实参;2) 函数参数形式更简单、直接3) 要求 形参:对象引用 实参:对象
二、对象指针和对象引用作函数参数 2. 对象引用作函数参数
[ 例 6.3] #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;};
void main( ){ M p(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);}
#include<iostream.h>
class Point
{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.X;
cout<<"fun(Point &p)."<<endl;
}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);
}
分析程序运行结果:
一、指向类成员的指针二、对象指针和对象引用作函数参数三、 this 指针
§§6.1 6.1 对象指针和对象引用对象指针和对象引用
三、 this 指针1. 隐含于每个类的成员函数中 ;2. 指向正在被成员函数操作的对象;3. 对象调用成员函数时,编译器先将该对象的地址赋给 this 指针,然后调用成员函数;4. 调用成员函数存取数据成员时,隐含使用 t
his 指针;一般不显示使用 this 指针引用数据成员。
对象指针
[ 例 6.4]
void main( ){ A a1, a2(3, 4); a1.copy(a2); a1.print( );}
3, 4
#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;};
void A::copy(A &aa){ if( this==&aa ) return; *this=aa; }
void A::copy(A &aa){ (*this).a =aa.a; (*this).b =aa.b;}
[ 例 6.4]
void main( ){ A a1, a2(3, 4); a1.copy(a2); a1.print( );}
#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;};
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 A::copy(A &aa){ (*this).a =aa.a; (*this).b =aa.b;}
[ 例 6.4]
void main( ){ A a1, a2(3, 4); a1.copy(a2); a1.print( );}
#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;};
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 A::copy(A &aa){ a =aa.a; b =aa.b;}
void A::copy(A &aa){ (*this).a=aa.a; (*this).b=aa.b;}
1. 隐含于每个类的成员函数中 ;2. 指向正在被成员函数操作的对象;3. 对象调用成员函数时,编译器先将该对象的地址赋给 this 指针,然后调用成员函数;4. 调用成员函数存取数据成员时,隐含使用 this 指针;一般不显示使用 this 指针引用数据成员。
三、 this 指针
非静态成员函数有隐含的“ this” 指针(指向对象); 静态成员函数没有隐含的“ this” 指针。因为静态函数属于类,直接操作类中的静态数据成员
所有的成员函数吗?
§§6.2 6.2 数 组数 组一、对象数组二、指向数组的指针和指针数组
一、对象数组
1.定义 < 类名 > < 数组名 >[< 大小 >]…
2.赋值 可以被赋初值,也可以被赋值; 数组元素下标:从 0 开始;
数组元素是同一个类的若干对象
[ 例 6.5]
void main( ){ DATE dates[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/20029/6/20029/7/20029/8/20029/9/2002
#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.2 6.2 数 组数 组
二、指向数组的指针和指针数组
(1)指向一般数组的指针
(2) 指向对象数组的指针
1. 指向数组的指针
< 类型说明符 > (*< 指针名 >) [< 大小 >]
例: int (*pa)[3];
< 类名 > (*< 指针名 >) [< 大小 >]
[ 例 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"; }}
1 2 3
4 5 6
7 8 9
int (*pa)[3] = a;
[ 例 6.7] 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;};void main( ){ M m[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; }}
12,20 14,30 16,40 18,5020,60 22,70 24,80 26,90
M (*pm)[4] =m;
(1) 一般的指针数组 (2) 对象指针数组
数组元素为指针的数组
二、指向数组的指针和指针数组2.指针数组
< 类型名 > * < 数组名 >[< 大小 >]…
< 类名 > * < 数组名 >[< 大小 >]…
数组元素:指向同一类对象的指针
常用:字符指针数组char * str[10];
[ 例 6.9]
void main( ){ A a1(7, 8), a2, a3(5, 7); A* b[3]={&a3, &a2, &a1}; // 对象指针数组 for(int i=0; i<3; i++) b[i]->print( );}
5, 70, 07, 8
数组元素:指向 A 类对象的指针
class A{ public: A(int i=0, int j=0) {a=i; b=j;} void print( ); private: int a, b;};
void A::print( ){ cout<<a<<","<<b<<endl; }
[ 例 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;};
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.3 6.3 常类型常类型一、一般常量和对象常量二、常指针和常引用三、常成员函数四、常数据成员
经 const 说明的类型,其值不能更新,定义时必须初始化!
一、一般常量和对象常量1) 简单类型
2) 常数组
1. 一般常量const < 类型 > < 常量名 > = < 值>< 类型 > const < 常量名 > = < 值>
例 : const int x=2;
例 : int const x=2;
const < 类型 > < 数组名 >[< 大小 >]…
< 类型 > const < 数组名 >[< 大小 >]…
数组元素的值不能更新例 : const int a[5]={1, 2, 3, 4, 5};例 : int const a[5]={1, 2, 3, 4, 5};
初始化
< 类名 > const < 对象名 >const < 类名 > < 对象名 >
例: const A a1(3, 4); // 常对象 a1
例: A const a2(8,19); // 常对象 a2
一、一般常量和对象常量2.常对象(对象常量)
定义常对象时要初始化 , 对象不能被更新class A{ public: A(int i, int j) {x=i; y=j;} private: int x, y;};
对象 a1 、 a2值不能再被更新
一、一般常量和对象常量二、常指针和常引用三、常成员函数四、常数据成员
经 const 说明的类型,其值不能更新,定义时必须初始化!§§6.3 6.3 常类型常类型
二、常指针和常引用
1) 指针常量: const 修饰指针时,随位置不同,含义不同!
2) 指向常量的指针:
指针常量 目标不能更改 能更改
1000
指针 目标常量能更改 不能更改
2000
1. 常指针< 类型 > * const< 指针名 >
const < 类型 > * < 指针名>
1) 指针常量:
2) 指向常量的指针:
指针常量 目标不能更改 能更改
1000
< 类型 > * const< 指针名 >
const < 类型 > * < 指针名>
const 修饰指针时,随位置不同,含义不同!1. 常指针
指针 目标常量能更改 不能更改
3000
二、常指针和常引用
1. 定义一个指向字符串 string1 的指针常量 ptr1 :
指针 ptr1 *ptr1
不能更改 能更改
2. 定义一个指向字符串常量 string1 的指针 ptr2 :
ptr2 常量 *ptr1
能更改 不能更改
于是 : ptr1=string2; ( ) 但 *ptr1=“abc”; ( )
于是 : *ptr2=“xyz”; ( ) ; 但 ptr2=string2; ( )
char * const ptr1= string1;
const char * ptr2= string1;
[ 例 6.11] #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;}
形参:指向整常量的指针
实参: int 型数组
一个能够被更新的变量使用在一个不能被更新的环境中,不破坏类型保护!
类型适应一种类型的对象能够用于另一种类型的对象使用的环境
“常引用”所引用对象的值不能被更新!const < 类型说明符 > &< 引用名 > = 初值< 类型说明符 > const &< 引用名 > = 初值
例: double x(6.6); const double &v =x; 则 v=12.3; ( )
注:常指针和常引用往往用作函数的参数,称“常参数”
二、常指针和常引用2. 常引用
[ 例 6.12]
void main( ){ K k1(8), k2(17); int s=add(k1, k2); // 实参 : 对象 cout<<s<<endl;}
25
class K{ public: K(int i) { k=i;} int setk() const { return k; } private: int k;};
int add(const K &g1, const K &g2){ int sum= g1.setk( ) + g2.setk( ); return sum;}
常引用作函数参数
? 常成员函数删除 const ,理解 this 和常函数
一、一般常量和对象常量二、常指针和常引用三、常成员函数四、常数据成员
经 const 说明的类型,其值不能更新,定义时必须初始化!§§6.3 6.3 常类型常类型
三、常成员函数1. 说明格式:
< 类型 > < 函数名 >(< 参数表 >) const;
2. “const” 作函数类型的一部分,函数实现也要带 const ;3. 常成员函数不更新对象的数据成员,也不能调用未经“ const” 修饰的成员函数;
可以用来操作常对象(常量)
[ 例 6.12]
void main( ){ K k1(8), k2(17); int s=add(k1, k2); cout<<s<<endl;}
class K{ public: K(int i) { k=i;} int setk() const { return k; } private: int k;};
int add(const K &g1, const K &g2){ int sum= g1.setk( ) + g2.setk( ); return sum;}
常引用
只有常成员函数操作常引用;非常引用可以操作常函数
常成员函数
[ 例 6.13]
void main( )
{ R a(5, 4);
a.print( );
const R b(20, 52);
b.print( );
}
class R
{ public:
R(int r1, int r2) { R1=r1; R2=r2; }
void print( );
void print( ) const;
private:
int R1, R2;
};
void R::print( )
{ cout<<R1<<";"<<R2<<endl; }
void R::print( ) const{ cout<<R1<<";"<<R2<<endl; }
const 可以参与区分函数重载说明
实现
操作常对象 b
< 类型 > < 函数名 >(< 参数表 >) const; 强调:只有常成员函数才有资格操作“常对象”
三、常成员函数
1. 未经 const 说明的成员函数不能操作“常对象”; 若一个对象说明为“常对象”,则它只能调用常成员函数,不能调用其他成员函数;2. 常成员函数不仅可以用于操作“常对象”,还可以操作“一般对象”。
[ 例 6.13]
void main( )
{ R a(5, 4);
a.print( );
const R b(20, 52);
b.print( );
}
class R
{ public:
R(int r1, int r2) { R1=r1; R2=r2; }
// void print( );
void print( ) const;
private:
int R1, R2;
};
void R::print( ) const{ cout<<R1<<";"<<R2<<endl; }
说明
实现
允许操作“一般对象”操作“常对象”
[ 例 6.13]
void main( )
{ R a(5, 4);
a.print( );
const R b(20, 52);
b.print( );
}
class R
{ public:
R(int r1, int r2) { R1=r1; R2=r2; }
void print( );
// void print( ) const;
private:
int R1, R2;
};
void R::print( )
{ cout<<R1<<";"<<R2<<endl; }
不允许操作“常对象”
一、一般常量和对象常量二、常指针和常引用三、常成员函数四、常数据成员
经 const 说明的类型,其值不能更新,定义时必须初始化!§§6.3 6.3 常类型常类型
四、常数据成员 const 类型量在对象定义时必须初始化;
通过“成员初始化列表”生成构造函数
类体中不允许对所定义的数据成员进行初始化;常数据成员的初始化方法
[ 例 6.14]
void main( ){ A a1(100), a2(0); a1.print( ); a2.print( );}
100: 10: 1000 : 10: 0
class A{ public: A(int i); void print( ); const int &r; // 常 int 型引用 private: const int a; // 常 int 型量 static const int b; // 静态常 int 型量};
A::A(int i) : a(i), r(a){ }void A::print( ){ cout<<a<<":"<<b<<":"<<r<<endl; }
数据成员初始化列表 const int A::b= 10; // 静态数据初始化
§§6.4 6.4 子对象和堆对象子对象和堆对象
2. 初始化 在构造函数中通过“成员初始化表”来初始化子对象;
1. 含义 一个类的成员是另一个类的对象;
一、子对象(对象成员)
[ 例 6.15]
void main( ){ B b(6,7, 8); b.print( );}
6, 7 8
class B{ public:
B(int i, int j, int k): a(i, j) { b=k; } void print(); private: A a; // 子对象 int b;};
子对象
class A{ 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; }
子对象调用成员函数
class B{ public:
B(int i, int j, int k): a(i, j), b(k) { } void print(); private: A a; // 子对象 int b;};
[ 例 6.15] 修改
void main( ){ B b(6,7, 8); b.print( );}
子对象 数据成员
class A{ 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; }
• 子对象的初始化 : < 子对象名 >(< 参数表>)
• 常数据成员的初始化• 其它数据成员的初始化
初始化在构造函数中通过“成员初始化表”完成。
一、子对象(对象成员)
二、堆对象 程序运行中根据需要由 new 建立和由 delete 删除的对象
动态分配内存空间运算符
1) 在堆中建立给定类型的对象,若无初始值,则为缺省值;2) 创建对象时,根据参数调用适当的构造函数;3) 返回值:指针
例 : A *ptr1; ptr1=new A(5, 6);例 : int *p; p=new int; 或 p=new int(5);
new < 类型 > <( 初始值列表 )>
1. 运算符 new
new 创建数组 :
a) 使用 new 创建数组时:不能指定初始值,其初始值为缺省值;b) 使用 new 创建对象数组时:类中必须定义缺省构造函数。 ( 因为不能指定初始值啊!)
new < 类型 >[< 大小 >]
一般数组 : int *p; p=new int[10];
对象数组 : A *ptr2; ptr2=new A[5];
具有 5 个元素的对象数组
检验 new 返回的指针,是否分配有效的内存空间
if( ! a1 ) { cout<<“Heap error! \n”; exit(1); }
“new” 返回值 成功:与分配对象类型相匹配的指针不成功 : 空指针 0
例: AA *a1=new AA(1, 2);
1) 功能:删除使用 new 创建的堆对象或一般类型堆变量;
2) 注意事项:
delete < 指针名 > A *ptr1=new A(5, 6);
delete ptr1;delete [ ] < 指针名 > A *ptr2=new A[5];
delete [ ] ptr2;
2. 运算符 delete
二、堆对象
void main( )
{
int *p, *q, a=5;
p = new int(10);
q = &a;
cout<<*p<<endl;
cout<<*q<<endl;
delete p;
delete q;
}
使用 delete 运算符时注意事项:
只能用于 new 返回的指针或空指针,不能用于其他指针!
void main( )
{
int *p, a=5;
p = new int(10);
cout<<*p<<endl;
delete p;
p = &a;
cout<<*p<<endl;
delete p;
}
使用 delete 运算符时注意事项:
一个指针只能使用一次 delete 操作!
delete 只释放指针指向的内存堆单元
[ 例 6.16]
void main( ) { AA *a1, *a2;
a1=new AA;a2=new AA(5, 6);a1->print( );a2->print( );delete a1;delete a2;
}
Default Constructor.Constructor. 0, 0 5, 6Destructor.Destructor.
void AA::print( ){ cout<<A<<","<<B<<endl; }
class AA{ public: AA( ) { A=B=0; cout<< “Default Constructor.\n"; } AA(int i, int j) { A=i; B=j; cout<<"Constructor.\n"; } ~AA() { cout<<"Destructor.\n"; } void print( ); private: int A, B;};
[ 例 6.16] 修改 void main() {
AA *a1, *a2;a1=new AA;a2=new AA(5, 6);a1->print( );a2->print( );// delete a1;// delete a2;
}
Default Constructor.Constructor.0, 05, 6
void AA::print( ){ cout<<A<<","<<B<<endl; }
class AA{ public: AA( ) { A=B=0; cout<< “Default Constructor.\n"; } AA(int i, int j) { A=i; B=j; cout<<"Constructor.\n"; } ~AA() { cout<<"Destructor.\n"; } void print( ); private: int A, B;};
只能通过显式使用delete 析构堆对象
[ 例 6.17]
void main( ){ B *p; double n; char s[80];
p=new B[3];
p[0]=B("ma", 4.8); p[1]=B("wu", 3.6); p[2]=B("li", 3.1);
for(int i=0; i<3; i++) { p[i].getb(s, n); cout<<s<<","<<n<<endl; }
delete [ ] p;}
DefaultDefaultDefault
ConstructorDestructor maConstructorDestructor wuConstructorDestructor li
ma, 4.8 w, 3.6 li, 3.1
Destructor liDestructor wuDestructor ma
class B{ public: B() {cout<<"Default\n";}
B(char *s, double n) { strcpy(name, s); b=n; cout<<"constructor\n"; }
~B( ) { cout<<"Destructor " <<name<<endl; }
void getb(char *s, double &n) { strcpy(s, name); n=b; } private: char name[80]; double b;};
1) 功能:删除使用 new 创建的堆对象或一般类型堆变量;2) 注意事项:
delete < 指针名 > delete [ ] < 指针名 >
2. 运算符 delete
二、堆对象
a. 用于 new 返回的指针,或空指针;b. 对一个指针只能用一次 delete ;c. 用 delete 删除堆对象时,调用析构函数;d. 指针名前只用一对 [ ] , 忽略括号内数字和维数。
§§6.5 6.5 类型转换类型转换一、类型的自动隐式转换二、构造函数的类型转换功能三、转换函数
将一种类型的值映射为另一类型的值
一、类型的自动隐式转换1. 算术运算时,低类型转换为高类型 ;
2. 赋值表达式中,右值转换为左值类型 , 再赋值 ; 例 : long var; var=10;
3. 函数调用时,实参转换为形参类型 , 赋给形参 ;例 : double f1(double d); double f; f=f1(10);
4. 函数返回值时,返回表达式类型转换为函数类型。 double f1(int d) { int m=d*2; return (m); }
二、构造函数的类型转换功能 单个参数的构造函数具有类型转换功能;
与其参数类型相同的“数值”
“该类对象”转换成
[ 例 6.19]
void main( ){ A a(5); a=10; a.print( );}
class A{ public: A( ) {m=0;} A(double i) { m=i; } void print() { cout<<m<<endl; } private: double m;};
10
[ 例 6.19] 修改
void main( ){ A a(5); a =10; a.print( );}
Constructor: 5
Constructor: 10Destructor: 1010Destructor: 10
通过标准数据类型转换,将整型值 10 转换成 double 型;通过单参数构造函数,将 double 型数值转换成 A 类类型;创建匿名对象,赋值后释放。
class A{ public: A() {m=0;} A(double i) { m=i; cout<<"Constructor: "<<m<<endl; } void print() { cout<<m<<endl; } ~A() { cout<<"Destructor: "<<m<<endl; } private: double m;};
三、转换函数
1) 非静态的成员函数;2) 不能定义为友元函数;3) 无返回值类型4) 不带参数
class < 类名 1>{ public: operator < 类型说明符 2>( ); ……} 函数名 , 目标类型
将 < 类名 1> 的类型转换为 < 类型说明符 2> 指定的类型
—“ 类型强制转换成员函数”
[ 例 6.20]
5.325
void main( ){ Rational r(5, 8); double d=4.7; d += r; cout<<d<<endl;}
( double(5)/double(8) )+4.7
class Rational{ public: Rational(int d, int n) { den=d; num=n; } operator double(); private: int den, num;};
Rational::operator double(){ return double(den)/double(num);}
函数名 , 目标类型
隐式类型转换
[ 例 6.20]
void main( ){ Rational r(5, 8); double d=4.7; d += double(r); cout<<d<<endl;}
class Rational{ public: Rational(int d, int n) { den=d; num=n; } operator double(); private: int den, num;};
Rational::operator double(){ return double(den)/double(num);}
显式类型转换
[ 例 6.20]
void main( ){ Rational r(5, 8); double d=4.7; d += r. operator double( ); cout<<d<<endl;}
class Rational{ public: Rational(int d, int n) { den=d; num=n; } operator double(); private: int den, num;};
Rational::operator double(){ return double(den)/double(num);}
利用对象直接调用成员函数
1) 非静态的成员函数;2) 不能定义为友元函数;3) 无返回值类型4) 不带参数
class < 类名 1>{ public: operator < 类型说明符 2>( ); ……}
函数名 , 目标类型
将 < 类名 1> 的类型转换为 < 类型说明符 2> 指定的类型
函数的名称即目标类型对本类型的操作数进行转换
有“ this” 指针
作 业 题作 业 题三 (1) 对象数组的定义、赋初值、赋值
void main( ){ cout<<"Starting1...\n"; A a[3]; for(int i=0; i<3; i++) a[i].Set(2*i+1, (i+1)*2); cout<<"Ending1...\n";
cout<<"starting2...\n"; A b[3]={A(1,2), A(3,4), A(5,6)}; cout<<"Ending2...\n";}
Starting1… Default Constructor called. Default Constructor called. Default Constructor called. Ending1…
Starting2… Constructor: a=1, b=2 Constructor: a=3, b=4 Constructor: a=5, b=6 Ending2…
Destructor called. a=5,b=6 Destructor called. a=3,b=4 Destructor called. a=1,b=2
Destructor called. a=5,b=6
Destructor called. a=1,b=2 Destructor called. a=3,b=4
三 (2)
void main( ){ B *ptr; ptr =new B[3]; ptr[0] = B( ); ptr[1] = B(5); ptr[2] = B(2, 3); for(int i=0; i<3; i++) ptr[i].Print( ); delete [] ptr;}
class B{ int x, y; public: B( ); B(int i); B(int i, int j); ~B( ); void Print( );};
Default constructor called.Default constructor called.Default constructor called.
Default constructor called.Destructor called.
Constructor1 called.Destructor called.
Constructor2 called.Destructor called.
x=0, y=0 x=5, y=0 x=2, y=3
Destructor called.Destructor called.Destructor called.
三(3)
void main( ){ const int N=5; A my; my = N; my.Print();}
Constructor called. 0Constructor called. 5Destructor called. 55Destructor called. 5
单参数构造函数的类型转换功能class A{ public: A(int i=0) {m=i; cout<<"Constructor called."<<m<<"\n";} void Set(int i) { m=i; } void Print() const { cout<<m<<endl; } ~A() {cout<<"Destructor called."<<m<<"\n";} private: int m;};
三 (4)
void main( ){ fun(5); }
Constructor called. 55Destructor called. 5
单参数构造函数的类型转换功能,常参数class A{ public: A(int i=0) {m=i; cout<<"Constructor called."<<m<<"\n";} void Set(int i) {m=i;} void Print() const { cout<<m<<endl; } ~A() { cout<<"Destructor called."<<m<<"\n"; } private: int m;};
void fun(const A &c){ c.Print(); }
常引用常成员函数操作常引用
三 (5)void main( ){ complex c1; complex c2(6. 8); complex c3(5.6, 7.9); c1.Print(); c2.Print(); c3.Print(); c1 = complex(1.2, 3.4); c2 = 5; c3 = complex( ); c1.Print(); c2.Print(); c3.Print();}
Default Constructor called. Constructor: real=6.8, imag=0 Constructor: real=5.6, imag=7.9
0 + 0i6.8 + 0i5.6 + 7.9i
Constructor: real=1.2, imag=3.4 Constructor: real=5, imag=0 Default Constructor called.
1.2 + 3.4i5 + 0i0 + 0i
实 验 实 验 三三1.设计一银行账户类的资金往来管理。1)数据包括:账号、姓名、密码、余额;2)实现的操作包括:开户、存款、取款、查询余额、修改密码;编程实现成员函数主体,实现主程序。
实验内容:
实 验 实 验 三三2.编程实现一个简单的售书程序,其中:
• Book 类包括书名、成本价等信息;• Sales 类包括书对象、售价、销售量等信息,统计销售额和销售利润;
为类建立一些必要的函数,最后统计销售总额和总利润。
实验内容: