第六章 类和对象
This presentation is the property of its rightful owner.
Sponsored Links
1 / 79

第六章 类和对象 ( 二 ) PowerPoint PPT Presentation


  • 101 Views
  • Uploaded on
  • Presentation posted in: General

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

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.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


4789911

第六章 类和对象(二)

§6.1对象指针和对象引用

§6.2数组

§6.3常类型

§6.4子对象和堆对象

§6.5类型转换


4789911

§6.1 对象指针和对象引用

一、指向类成员的指针

二、对象指针和对象引用作函数参数

三、 this指针


4789911

<对象>.*<指针名>

<指向对象的指针> ->*<指针名>

一、指向类成员的指针

1. 指向数据成员的指针

定义

<类型说明符>*<指针名>

赋值

<指针名> =&<数据成员名>

<类名>::

<类名>::

  • 使用

通过“对象”来引用指针“指向的成员”

成员指针运算符


4789911

(对象.*<指针名>)(<参数表>)

(指向对象的指针->*<指针名>)(<参数表>)

一、指向类成员的指针

2. 指向成员函数的指针

定义

<类型>( *<指针名>) (<参数表>)

赋值

<指针名> = <成员函数名>

<类名>::

<类名>::

  • 引用

成员指针运算符


4789911

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;


4789911

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


4789911

§6.1 对象指针和对象引用

一、指向类成员的指针

二、对象指针和对象引用作函数参数

三、 this指针


4789911

  • 实现“传址调用”,被调函数中通过改变形参指针所指对象的值来影响实参;

  • 只将实参的地址传给形参,不进行副本拷贝,

  • 减少时空开销,提高运行效率;

  • 要求 形参:对象指针

  • 实参:对象的地址值

二、对象指针和对象引用作函数参数

1.对象指针作函数参数


4789911

#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


4789911

  • 具有对象指针作函数参数的优点,被调函数中通过改变引用的值来直接影响实参;

  • 函数参数形式更简单、直接

  • 要求 形参:对象引用

  • 实参:对象

二、对象指针和对象引用作函数参数

2.对象引用作函数参数


4789911

#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);

}


4789911

分析程序运行结果:

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);

}


4789911

§6.1 对象指针和对象引用

一、指向类成员的指针

二、对象指针和对象引用作函数参数

三、 this指针


4789911

三、this指针

对象指针

  • 隐含于每个类的成员函数中;

  • 指向正在被成员函数操作的对象;

  • 对象调用成员函数时,编译器先将该对象的地址赋给this指针,然后调用成员函数;

  • 调用成员函数存取数据成员时,隐含使用this指针;一般不显示使用this指针引用数据成员。


4789911

#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


4789911

#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;

}


4789911

#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;

}


4789911

三、this指针

所有的成员函数吗?

  • 隐含于每个类的成员函数中;

  • 指向正在被成员函数操作的对象;

  • 对象调用成员函数时,编译器先将该对象的地址赋给this指针,然后调用成员函数;

  • 调用成员函数存取数据成员时,隐含使用this指针;一般不显示使用this指针引用数据成员。

  • 非静态成员函数有隐含的“this”指针(指向对象);

  • 静态成员函数没有隐含的“this”指针。因为静态函数属于类,直接操作类中的静态数据成员


4789911

§6.2 数 组

一、对象数组

二、指向数组的指针和指针数组


4789911

一、对象数组

  • 数组元素是同一个类的若干对象

  • 定义

  • <类名><数组名>[<大小>]…

  • 赋值

  • 可以被赋初值,也可以被赋值;

  • 数组元素下标:从0开始;


4789911

#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


4789911

§6.2 数 组

一、对象数组

二、指向数组的指针和指针数组


4789911

二、指向数组的指针和指针数组

1. 指向数组的指针

  • 指向一般数组的指针

  • (2) 指向对象数组的指针

<类型说明符> (*<指针名>)[<大小>]

例:int (*pa)[3];

<类名> (*<指针名>) [<大小>]


4789911

[例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


4789911

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


4789911

二、指向数组的指针和指针数组

  • 指针数组

  • 数组元素为指针的数组

(1) 一般的指针数组

(2) 对象指针数组

常用:

字符指针数组

char* str[10];

<类型名> *<数组名>[<大小>]…

<类名> *<数组名>[<大小>]…

数组元素:指向同一类对象的指针


4789911

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


4789911

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;

};


4789911

§6.3 常类型

  • 经const说明的类型,其值不能更新,定义时必须初始化!

一、一般常量和对象常量

二、常指针和常引用

三、常成员函数

四、常数据成员


4789911

例: 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 <数组名>[<大小>]…


4789911

一、一般常量和对象常量

  • 常对象(对象常量)

<类名>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


4789911

§6.3 常类型

  • 经const说明的类型,其值不能更新,定义时必须初始化!

一、一般常量和对象常量

二、常指针和常引用

三、常成员函数

四、常数据成员


4789911

目标

指针常量

1000

不能更改

能更改

目标常量

指针

2000

能更改

不能更改

二、常指针和常引用

1. 常指针

  • const修饰指针时,随位置不同,含义不同!

<类型>*const<指针名>

  • 指针常量:

  • 指向常量的指针:

const<类型>* <指针名>


4789911

目标

指针常量

不能更改

能更改

目标常量

指针

3000

能更改

不能更改

二、常指针和常引用

1. 常指针

  • const修饰指针时,随位置不同,含义不同!

<类型>*const<指针名>

  • 指针常量:

1000

const<类型> * <指针名>

  • 指向常量的指针:


4789911

*ptr1

指针ptr1

不能更改

能更改

常量*ptr1

ptr2

能更改

不能更改

  • 定义一个指向字符串string1的指针常量ptr1:

char* const ptr1= string1;

于是:ptr1=string2; (  )但*ptr1=“abc”; ( )

  • 定义一个指向字符串常量string1的指针ptr2:

const char* ptr2= string1;

于是: *ptr2=“xyz”; ( ) ; 但 ptr2=string2; ( )


4789911

类型适应

一种类型的对象能够用于另一种类型的对象使用的环境

#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型数组

形参:指向整常量的指针

一个能够被更新的变量使用在一个不能被更新的环境中,不破坏类型保护!


4789911

二、常指针和常引用

2. 常引用

  • “常引用”所引用对象的值不能被更新!

const<类型说明符>&<引用名> = 初值

<类型说明符>const&<引用名> = 初值

  • 例: double x(6.6);

    • const double&v =x;

    • 则 v=12.3; (  )

注:常指针和常引用往往用作函数的参数,称“常参数”


4789911

?常成员函数删除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


4789911

§6.3 常类型

  • 经const说明的类型,其值不能更新,定义时必须初始化!

一、一般常量和对象常量

二、常指针和常引用

三、常成员函数

四、常数据成员


4789911

三、常成员函数

  • 说明格式:

<类型> <函数名>(<参数表>)const;

  • “const”作函数类型的一部分,函数实现也要带const;

  • 常成员函数不更新对象的数据成员,也不能调用未经“const”修饰的成员函数;

可以用来操作常对象(常量)


4789911

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;

}


4789911

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


4789911

三、常成员函数

<类型> <函数名>(<参数表>)const;

  • 强调:只有常成员函数才有资格操作“常对象”

  • 未经const 说明的成员函数不能操作“常对象”;

  • 若一个对象说明为“常对象”,则它只能调用常成员函数,不能调用其他成员函数;

  • 常成员函数不仅可以用于操作“常对象”,还可以操作“一般对象”。


4789911

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; }

允许操作“一般对象”

操作“常对象”


4789911

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( );

}

不允许操作“常对象”


4789911

§6.3 常类型

  • 经const说明的类型,其值不能更新,定义时必须初始化!

一、一般常量和对象常量

二、常指针和常引用

三、常成员函数

四、常数据成员


4789911

常数据成员的初始化方法

四、常数据成员

  • const 类型量在对象定义时必须初始化;

  • 类体中不允许对所定义的数据成员进行初始化;

通过“成员初始化列表”生成构造函数


4789911

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


4789911

§6.4 子对象和堆对象

一、子对象(对象成员)

  • 含义

  • 一个类的成员是另一个类的对象;

  • 初始化

  • 在构造函数中通过“成员初始化表”来初始化子对象;


4789911

[例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


4789911

[例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( );

}


4789911

一、子对象(对象成员)

初始化

在构造函数中通过“成员初始化表”完成。

  • 子对象的初始化: <子对象名>(<参数表>)

  • 常数据成员的初始化

  • 其它数据成员的初始化


4789911

动态分配内存空间运算符

1.运算符new

new<类型> <(初始值列表)>

二、堆对象

  • 程序运行中根据需要由new建立和由delete删除的对象

在堆中建立给定类型的对象,若无初始值,则为缺省值;

创建对象时,根据参数调用适当的构造函数;

返回值:指针

例:int *p; p=newint; 或 p=newint(5);

例:A *ptr1; ptr1=newA(5, 6);


4789911

一般数组: int *p; p=newint[10];

对象数组: A *ptr2; ptr2=newA[5];

new创建数组:

new<类型>[<大小>]

具有5个元素的

对象数组

使用new 创建数组时:不能指定初始值,其初始值为缺省值;

使用new创建对象数组时:类中必须定义缺省构造函数。(因为不能指定初始值啊!)


4789911

成功:与分配对象类型相匹配的指针

不成功: 空指针0

“new”返回值

检验new返回的指针,是否分配有效的内存空间

例:AA *a1=new AA(1, 2);

if( ! a1 )

{

cout<<“Heap error! \n”;

exit(1);

}


4789911

二、堆对象

2. 运算符delete

  • 功能:删除使用new创建的堆对象或一般类型堆变量;

A *ptr1=new A(5, 6);

deleteptr1;

delete<指针名>

A *ptr2=new A[5];

delete [ ]ptr2;

delete[ ] <指针名>

  • 注意事项:


4789911

void main( )

{

int *p, *q, a=5;

p = new int(10);

q = &a;

cout<<*p<<endl;

cout<<*q<<endl;

deletep;

delete q;

}

  • 使用delete运算符时

    注意事项:

只能用于new 返回的指针或空指针,不能用于其他指针!


4789911

void main( )

{

int *p, a=5;

p = new int(10);

cout<<*p<<endl;

deletep;

p = &a;

cout<<*p<<endl;

delete p;

}

  • 使用delete运算符时

    注意事项:

delete只释放指针指向的内存堆单元

一个指针只能使用一次delete操作!


4789911

[例6.16]

classAA

{ 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;

};

  • void main( )

  • {

  • AA*a1, *a2;

    • a1=newAA;

    • a2=newAA(5, 6);

    • a1->print( );

    • a2->print( );

    • deletea1;

    • delete a2;

  • }

Default Constructor.

Constructor.

0, 0

5, 6

void AA::print( )

{ cout<<A<<","<<B<<endl; }

Destructor.

Destructor.


4789911

Default Constructor.

Constructor.

0, 0

5, 6

[例6.16]修改

classAA

{ 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;

};

  • void main()

  • {

    • AA*a1, *a2;

    • a1=newAA;

    • a2=newAA(5, 6);

    • a1->print( );

    • a2->print( );

    • // deletea1;

    • // delete a2;

  • }

只能通过显式使用delete析构堆对象

void AA::print( )

{ cout<<A<<","<<B<<endl; }


4789911

[例6.17]

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;

};

void main( )

{

B*p;

double n;

char s[80];

p=newB[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;

}

Default

Default

Default

Constructor

Destructor ma

Constructor

Destructor wu

Constructor

Destructor li

ma, 4.8

w, 3.6

li, 3.1

Destructor li

Destructor wu

Destructor ma


4789911

二、堆对象

2. 运算符delete

  • 功能:删除使用new创建的堆对象或一般类型堆变量;

delete<指针名>

delete[ ] <指针名>

  • 注意事项:

  • 用于new 返回的指针,或空指针;

  • 对一个指针只能用一次delete;

  • 用delete删除堆对象时,调用析构函数;

  • 指针名前只用一对[ ] ,忽略括号内数字和维数。


4789911

§6.5 类型转换

  • 将一种类型的值映射为另一类型的值

一、类型的自动隐式转换

二、构造函数的类型转换功能

三、转换函数


4789911

一、类型的自动隐式转换

  • 算术运算时,低类型转换为高类型;

  • 赋值表达式中,右值转换为左值类型, 再赋值;

  • 例:long var; var=10;

  • 函数调用时,实参转换为形参类型, 赋给形参;

    例: double f1(double d); double f; f=f1(10);

  • 函数返回值时,返回表达式类型转换为函数类型。

double f1(int d)

{ intm=d*2;

return (m);

}


4789911

转换成

二、构造函数的类型转换功能

  • 单个参数的构造函数具有类型转换功能;

与其参数类型相同的“数值”

“该类对象”


4789911

[例6.19]

classA

{ public:

A( ) {m=0;}

A(double i) { m=i; }

void print() { cout<<m<<endl; }

private:

double m;

};

void main( )

{

Aa(5);

a=10;

a.print( );

}

10


4789911

Constructor: 10

Destructor: 10

[例6.19]修改

classA

{ 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;

};

void main( )

{

Aa(5);

a=10;

a.print( );

}

Constructor: 5

通过标准数据类型转换,将整型值10转换成double型;

通过单参数构造函数,将double型数值转换成A类类型;创建匿名对象,赋值后释放。

10

Destructor: 10


4789911

三、转换函数

—“类型强制转换成员函数”

class <类名1>

{ public:

operator <类型说明符2>( );

……

}

函数名, 目标类型

  • 将<类名1>的类型转换为<类型说明符2>指定的类型

非静态的成员函数;

不能定义为友元函数;

无返回值类型

不带参数


4789911

class Rational

{ public:

Rational(int d, int n) { den=d; num=n; }

operator double();

private:

int den, num;

};

[例6.20]

函数名, 目标类型

Rational::operatordouble()

{

return double(den)/double(num);

}

隐式类型转换

void main( )

{ Rationalr(5, 8);

doubled=4.7;

d += r;

cout<<d<<endl;

}

5.325

( double(5)/double(8) )+4.7


4789911

class Rational

{ public:

Rational(int d, int n) { den=d; num=n; }

operator double();

private:

int den, num;

};

[例6.20]

Rational::operatordouble()

{

return double(den)/double(num);

}

显式类型转换

void main( )

{ Rational r(5, 8);

double d=4.7;

d += double(r);

cout<<d<<endl;

}


4789911

class Rational

{ public:

Rational(int d, int n) { den=d; num=n; }

operator double();

private:

int den, num;

};

[例6.20]

Rational::operatordouble()

{

return double(den)/double(num);

}

void main( )

{ Rational r(5, 8);

double d=4.7;

d += r. operatordouble( );

cout<<d<<endl;

}

利用对象直接调用成员函数


4789911

class <类名1>

{ public:

operator <类型说明符2>( );

……

}

函数名, 目标类型

  • 将<类名1>的类型转换为<类型说明符2>指定的类型

非静态的成员函数;

不能定义为友元函数;

无返回值类型

不带参数

有“this”指针

函数的名称即目标类型

对本类型的操作数进行转换


4789911

Default Constructor called.

Default Constructor called.

Default Constructor called.

Constructor: a=1, b=2

Constructor: a=3, b=4

Constructor: a=5, b=6

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=3,b=4

Destructor called. a=1,b=2

作 业 题

Starting1…

三(1)对象数组的定义、赋初值、赋值

Ending1…

void main( )

{

cout<<"Starting1...\n";

Aa[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";

}

Starting2…

Ending2…


4789911

classB

{ 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.

三(2)

Default constructor called.

Destructor called.

Constructor1 called.

Destructor called.

void main( )

{

B *ptr;

ptr =newB[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;

}

Constructor2 called.

Destructor called.

x=0, y=0

x=5, y=0

x=2, y=3

Destructor called.

Destructor called.

Destructor called.


4789911

Constructor called. 5

Destructor called. 5

单参数构造函数的类型转换功能

三(3)

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 main( )

{

const int N=5;

A my;

my = N;

my.Print();

}

Constructor called. 0

5

Destructor called. 5


4789911

单参数构造函数的类型转换功能,常参数

三(4)

class A

{ public:

A(int i=0) {m=i; cout<<"Constructor called."<<m<<"\n";}

void Set(int i) {m=i;}

voidPrint()const { cout<<m<<endl; }

~A() { cout<<"Destructor called."<<m<<"\n"; }

private:

int m;

};

void fun(constA&c)

{

c.Print();

}

常引用

常成员函数操作常引用

void main( )

{

fun(5);

}

Constructor called. 5

5

Destructor called. 5


4789911

0 + 0i

6.8 + 0i

5.6 + 7.9i

1.2 + 3.4i

5 + 0i

0 + 0i

三(5)

void main( )

{

complexc1;

complexc2(6. 8);

complexc3(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

Constructor: real=1.2, imag=3.4

Constructor:real=5, imag=0

Default Constructor called.


4789911

实 验 三

实验内容:

  • 设计一银行账户类的资金往来管理。

    • 数据包括:账号、姓名、密码、余额;

    • 实现的操作包括:开户、存款、取款、查询余额、修改密码;

    • 编程实现成员函数主体,实现主程序。


4789911

实 验 三

实验内容:

  • 编程实现一个简单的售书程序,其中:

    • Book类包括书名、成本价等信息;

    • Sales类包括书对象、售价、销售量等信息,统计销售额和销售利润;

  • 为类建立一些必要的函数,最后统计销售总额和总利润。


  • Login