《面向对象程序设计》实验指导书实验二.docx

上传人:b****7 文档编号:9334278 上传时间:2023-02-04 格式:DOCX 页数:22 大小:20.96KB
下载 相关 举报
《面向对象程序设计》实验指导书实验二.docx_第1页
第1页 / 共22页
《面向对象程序设计》实验指导书实验二.docx_第2页
第2页 / 共22页
《面向对象程序设计》实验指导书实验二.docx_第3页
第3页 / 共22页
《面向对象程序设计》实验指导书实验二.docx_第4页
第4页 / 共22页
《面向对象程序设计》实验指导书实验二.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

《面向对象程序设计》实验指导书实验二.docx

《《面向对象程序设计》实验指导书实验二.docx》由会员分享,可在线阅读,更多相关《《面向对象程序设计》实验指导书实验二.docx(22页珍藏版)》请在冰豆网上搜索。

《面向对象程序设计》实验指导书实验二.docx

《面向对象程序设计》实验指导书实验二

实验二类与对象㈡——对象初始化、对象数据与指针

一、实验目的

1.理解构造函数、析构函数的意义及作用,掌握构造函数、析构函数的定义及调用时间,熟悉构造函数的种类;

2.理解this指针及使用方法,熟悉对象数组、对象指针、对象引用的定义及使用方法,熟悉对象作为函数参数的使用方法;

3.熟悉类与对象的应用及编程。

二、实验学时

课内实验:

2课时课外练习:

2课时

三本实验涉及的新知识

㈠构造函数与析构函数

在C++中,提供了两个特殊的成员函数,即构造函数和析构函数。

构造函数用于对象的初始化,即在定义一个类对象时,计算机在给对象分配相应的存储单元的同时,为对象的数据成员赋初值。

析构执行的是与构造函数相反的操作,用于撤销对象的同时释放对象所占用的内存空间。

1.构造函数

⑴构造函数的定义

格式:

类名(形参表)

{构造函数体}

⑵构造函数的调用

构造函数的调用是在定义对象时调用的。

格式:

类名对象名(实参表);

类名对象名=构造函数名(实参表);

⑶说明

①构造函数必须与类同名。

②构造函数没有返回值,但不能在构造函数前加void类型符(其他没有返回值的成员函数必须加类型符void)。

③在实际应用中,在定义类时通常应定义一至多个构造函数(重载),以对各数据成员进行初始化;如果不给出构造函数,系统将自定义一个构造函数。

④构造函数可以可以带参数,也可不带任何参数(称无参构选函数),还可以使用缺省参数。

⑤不能象普通成员函数一样单独调用。

2.析构函数

⑴析构函数的定义

格式:

~类名(void)

{析构函数体}

⑵析构函数的调用

析构函数是在撤销对象时自动调用的。

⑶说明

⑴析构函数与构造函数的名字相同,但在其前面加上“~”,如果未定义析构函数,系统将自定义一个析构函数。

⑵析构函数没有参数、没有返回值,也不能重载。

⑶对于大多数类而言,可以缺省析构函数的定义,但是,当类的数据成员中使用指针变量,在构造函数中用new动态分配内存空间时,应显式定义析构函数,用delete释放已分配的内存空间。

3.拷贝构造函数(复制构造函数)

⑴拷贝构造函数的定义

格式:

类名([const]类名&对象名)

{拷贝构造函数体}

⑵拷贝构造函数的调用

拷贝构造函数是在对象间相互赋值时自动调用的。

格式:

目标对象名=源对象名;

目标对象名(源对象名);

⑶说明

①拷贝构造函数无返回值,也不能有void。

②如果不定义拷贝构造函数,系统会自定义一个拷贝构造函数,实现对数据成员的拷贝。

③默认拷贝构造函数是一种浅拷贝,当在类中定义有指针数据成员,用new分配内存空间时,通常应显示定义相应的拷贝构造函数。

㈡对象数组与对象指针

1.对象数组

⑴可以定义对象数组处理多个对象。

⑵可以用缺省参数构造函数为对象数组赋初值。

2.对象指针

可以使用指针来使用对象或对象数组。

方法:

⑴定义对象指针;

⑵将指针指向某一对象(或对象数组);

⑶用指针使用用对象(或对象数组元素):

对象指针->公有成员

3.对象引用

可以定义对象的引用,其引用名即为对象的别名。

4.this指针

⑴C++提供了一个特殊的对象指针,称为this指针。

⑵this指针为成员函数所属对象的指针,指向对象的首地址。

⑶this指针是一种隐含指针,隐含于每个类的成员函数中,即调用某成员函数时,都将自动产生一个this指针。

⑷调用this指针格式:

this->成员名

⑸this指针通常采用隐式调用,即在类内部直呼其名。

⑹this指针是系统自定义的,用户不能再定义

㈢对象作为函数的参数

在C++中,可以用对象作为函数的形参或实参。

主要有以下形式:

1.形参、实参均为对象,其参数的传递为对象的值,即为传值调用。

2.形参为对象指针,实参为对象指针或对象地址,其参数的传递为对象的地址,即传址调用。

3.形参为对象引用,实参为对象,形参是实参对象的别名,即传址调用。

4.形参、实参为对象指针或对象数组,为传址调用。

四、实验内容

㈠验证及认知实验

按要求调试下列程序,并回答相关问题。

程序1(exp_201.cpp)

#include

classMyclass

{

public:

Myclass(void)

{cout<<"constructing!

"<

~Myclass(void)

{cout<<"destructing!

"<

};

voidmain()

{Myclassob;}

问题:

⑴运行程序的输出结果为:

Constructing!

Destructing!

Pressanykeytocontinue

⑵该输出结果说明构造函数Myclass()是在创建对象时执行的,而析构函数~Myclass()是在是在对象生存期结束时执行的。

⑶将main()中的“Myclassob;”改为:

“Myclassob[2];”后,运行程序的输出结果为:

Constructing!

Constructing!

Destructing!

Destructing!

Pressanykeytocontinue

⑷将main()中的“Myclassob[2];”改为:

“Myclass*ob;ob=newMyclass[2];”后,运行程序的输出结果为:

Constructing!

Constructing!

Pressanykeytocontinue

⑸在⑷的基础上,在程序的末尾加入:

“delete[]ob;”后,运行程序的输出结果为:

Constructing!

Constructing!

Destructing!

Destructing!

Pressanykeytocontinue

⑹比较⑶—⑸的输出结果,说明:

程序2(exp_202.cpp)

#include

classA

{private:

inta,b;

public:

A(void)

{a=0;b=0;}

A(intx1,intx2)

{a=x1;b=x2;}

A(A&ob)

{a=ob.a;b=ob.b;

cout<<"拷贝构造函数被调用!

"<

}

voidprint(void)

{cout<<"a="<

};

voidmain()

{Aob1(20,30),ob;

Aob2(ob1);

ob2.print();

//ob=ob1;

//ob.print();

}

问题:

⑺运行该程序的输出结果为:

拷贝构造函数被调用!

a=20b=30

Pressanykeytocontinue

⑻程序中的成员函数A(A&ob)称为拷贝构造函数,该函数的执行时间是在执行用类的一个已知对象初始化类的另一个对象被调用的。

⑼将main()中的“Aob2(ob1);”改为“Aob2=ob1;”,重新运行程序,观察输出结果,说明拷贝构造函数也可在用类的一个已知对象给另一个类的对象赋值时时调用。

⑽将main()函数中加注释的语句去掉前面的“//”,重新运行程序,观测输出结果,说明执行“ob=ob1;”时不调用拷贝构造函数,原因是“ob=ob1;”只是对象的赋值。

㈡知识应用实验

1.分析下列程序,写出程序的输出结果,再上机运行程序验证其正确性,如果不正确,请认真分析出错原因。

你分析的程序输出结果是:

构造函数被调用!

Main:

a=10b=10

调用func1:

拷贝构造函数被调用!

Func1:

a=10b=10

析构函数被调用!

调用func2:

Func2:

a=10b=10

调用func3:

Main:

a=10b=10

析构函数被调用!

程序3(exp_203.cpp)

#include

classMyclass

{private:

inta,b;

public:

Myclass(intx1=0,intx2=0)

{a=x1;b=x2;

cout<<"构造函数被调用!

"<

}

~Myclass()

{cout<<"析构函数被调用!

"<

Myclass(Myclass&ob)

{a=ob.a;b=ob.b;

cout<<"拷贝构造函数被调用!

"<

}

voidprint(void)

程序的实际输出结果是:

构造函数被调用!

Main:

a=10b=10

调用func1:

拷贝构造函数被调用!

Func1:

a=10b=10

析构函数被调用!

调用func2:

Func2:

a=10b=10

调用func3:

Main:

a=10b=10

析构函数被调用!

{cout<<"a="<

};

voidfunc1(Myclassob)

{cout<<"func1:

";

ob.print();

}

voidfunc2(Myclass*ob)

{cout<<"func2:

";

ob->print();

}

voidfunc3(Myclass&ob)

{cout<<"func3:

";

ob.print();

}

voidmain()

{Myclassob(10,10);

cout<<"main:

";ob.print();

cout<<"调用func1:

"<

func1(ob);

cout<<"调用func2:

"<

func2(&ob);

cout<<"调用func3:

"<

func3(ob);

cout<<"main:

";ob.print();

}

2.完善、调试通过下列程序,并按所要求回答问题。

程序4(exp_204.cpp)

#include

#include

classperson

{private:

char*name;

public:

person(char*pn);//构造函数声明

~person(void);//析构函数声明

person(constperson&ob);//拷贝构造函数声明

char*get_name(void)

{returnname;}

voidprint_name(void);

};

①:

:

person(char*pn)//定义构造函数,为name提供值

{name=②;

if(name!

=NULL)

③;

}

①:

:

~person(void)//显示定义析构函数

{delete[]name;

}

①:

:

person(constperson&ob)//定义拷贝构造函数

{name=④;

if(name!

=NULL)

⑤;

}

voidperson:

:

print_name(void)

{cout<

voidmain(void)

{personp1("张三");

personp2=p1;

cout<<"姓名:

";p1.print_name();

cout<<"姓名:

";p2.print_name();

}

问题:

⑾程序中①处应为person;

②处应为newchar[strlen(pn)+1];;

③处应为strcpy(name,pn);;

④处应为newchar[strlen(ob.name)+1];;

⑤处应为strcpy(name,ob.name);;

程序5(exp_102.cpp)

//头文件“hscore.h”内容:

定义一个成绩类:

最多可以处理10科成绩及平均成绩

constintM=10;

classscore

{private:

floatsc[M],aver;//表示M科成绩的数组及平均成绩

intm;//表示实际考试科数

public:

score(void);//无参构造函数

score(floatx[],intn);//构造函数重载——初始化成绩

voidset_score(floatx[],intn);//提供成绩

floatget_score(inti)//得到第i科成绩

{returnsc[i];}

floatget_aver(void)//得到平均成绩

{returnaver;}

voidprint_score(void);

};

score:

:

score(void)//无参构造函数

{inti;

m=M;

for(i=0;i

sc[i]=0;

aver=0;

}

score:

:

score(floatx[],intn)//构造函数重载——初始化成绩

{inti;floatsum=0;

m=n;

①;

aver=sum/m;

}

voidscore:

:

set_score(floatx[],intn)//提供成绩

{inti;floatsum=0;

m=n;

②;

aver=sum/m;

}

voidscore:

:

print_score(void)//输出成绩、平均成绩

{inti;

for(i=0;i

cout<<""<

cout<<""<

}

问题:

⑿完善类的定义,程序中,①处应改为:

for(i=0,i

{sc[i]=x[i];

sum+=sc[i];}

②处应改为:

for(i=0,i

{sc[i]=x[i];

sum+=sc[i];}

//程序“exp_205.cpp”:

用成绩类“score”处理成绩:

任意个学生,任意科(不超过10科)

#include

#include"hscore.h"//调入成绩score类的定义头文件

voidinput(score*p,intn,intm);//普通函数:

输入学生成绩

voidprint(score*p,intn,intm);//普通函数:

输出学生成绩

score&average(score*p,intn,intm);//普通函数:

平均成绩计算

voidsort(score*p,intn,intm);//普通函数:

按平均成绩排序

voidmain(void)

{intn,m;

cout<<"学生人数:

";cin>>n;

cout<<"考试科数:

";cin>>m;

score*p,aver;

p=①;//动态数组:

用于处理n个学生成绩

if(p==NULL)

{cout<<"内存分配失败!

"<

return;

}

input(②);//调用输入成绩函数

print(②);//调用输出成绩函数

aver=average(②);//调用平均值计算函数

aver.print_score();//输出各科平均成绩

sort②);//成绩排序

print(②);//调用输出成绩函数

③;//释放内存

}

voidinput(score*p,intn,intm)

{inti,j;floatx[M];

for(i=0;i

{cout<<"第"<

"<

for(j=0;j

{cout<<"第"<

";

cin>>x[j];

}

④;//为某个学生对象提供成绩

}

}

voidprint(score*p,intn,intm)//成绩输出函数

{inti;

for(i=0;i

⑤;//输出某学生的成绩

}

score&average(score*p,intn,intm)//用返回引用的方法

{inti,j;floats[M]={0};

staticscoreaver;//返回的对象必须是静态的

for(j=0;j

{for(i=0;i

s[j]=s[j]+p[i].get_score(j);

s[j]=s[j]/n;

}

⑥;//对平均成绩对象提供值

returnaver;

}

voidsort(score*p,intn,intm)//选择法排序:

按平均成绩由高到低排列

{scoret;floata;

inti,j,k;

for(i=0;i

{a=p[i].get_aver();k=i;

for(j=i+1;j

if(a

{⑦}

if(k!

=i)

{⑧}

}

}

⒀完善main()函数,程序中

①处应为newscore[n];

②处应为p,n,m;

③处应为delete[]p;;

④处应为p->set_score(x,j);

⑤处应为cout<get_score(i)<

⑥处应为p->set_score(s,n);

⑦处应为a=p[j].get_aver();

⑧处应为cout<<""<

㈢程序设计实验

模拟一个裁判给比赛选手打分。

1.要求如下:

⑴裁判人数为UMPIRE;

⑵参赛选手为任意人;

⑶裁判给选手打分;

⑷去掉一个最高分,一个最低分,取其平均分为选手得分;

⑸按参赛选手的序号显示选手得分;

⑹按名次显示参赛选手得分(用插入法排序)。

2.提示:

⑴定义一个类名为Result的记分类为选手记分,数据成员至少包括选手编号(用整型)、姓名(用字符数组)、裁判为选手的打分及得分(用实型数组)等,成员函数自定(必须有构造函数),将类的定义保存在“result.h”中;

⑵测试程序(保存在exp_206.cpp中)采用交互方式:

①提示输入参赛选手人数;

②提示输入所有参赛选手的编号及姓名;

③显示比赛开始,请为选手打分;

④显示:

去掉的最高分、最低分,选手得分;

⑤比赛结束,按编号显示选手的得分;

⑥按名次显示选手得分。

#include

#include

#include

usingnamespacestd;

classresult

{

private:

intid;

stringname;

floatscore[5];

floatave;

public:

result(inti,stringn,floats[5])

{

floatsum=0,max=s[0],min=s[0];

intj;

id=i;

name.assign(n);

for(j=0;j<5;j++)

{

score[j]=s[j];

if(max

max=s[j];

if(min>s[j])

min=s[j];

sum+=s[j];

}

ave=(sum-max-min)/5;

}

floatget_ave()

{

returnave;

}

intget_id()

{

returnid;

}

stringget_name()

{

returnname;

}

voiddisplay()

{

inti;

cout<<"编号:

"<

"<

cout<<"最终得分="<

cout<<"评委打分:

";

for(i=0;i<5;i++)

cout<

cout<

}

};

voidmain()

{

inti,j;

intm;

intidsize;

cout<<"请输入参赛选手人数"<

cin>>m;

idsize=m;

int*id;//用指针指向一个数组

id=newint[idsize];//动态内存分配

vectoraver;

vectorname;

vector>x(m,vector(5));

cout<<"请输入所有参赛选手信息"<

for(i=0;i

{

stringna;

cout<<"第"<

cin>>id[i];

cout<<"第"<

cin>>na;

name.push_back(na);

}

cout<

for(i=0;i

{

cout<<"为第"<

for(j=0;j<5;j++)

{

cout<<"第"<

cin>>x[i][j];

}

}

cout<

for(i=0;i

{

floats[5];

for(j=0;j<5;j++)

s[j]=x[i][j];

resulta(id[i],name[i],s);

a.display();

aver.push_back(a.get_ave());

}

for(i=1;i

for(j=i;j>0;j--)

{

if(aver[j]

{

floattemp=aver[j];

aver[j]=aver[j-1];

aver[j-1]=temp;

intsum

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

当前位置:首页 > 高等教育 > 文学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1