《面向对象程序设计》C++实验指导书.docx
《《面向对象程序设计》C++实验指导书.docx》由会员分享,可在线阅读,更多相关《《面向对象程序设计》C++实验指导书.docx(22页珍藏版)》请在冰豆网上搜索。
《面向对象程序设计》C++实验指导书
实验1类和对象
1.1实验目的和要求
(1)理解类和对象的概念,掌握声明类和定义对象的方法。
(2)掌握构造函数和析构函数的实现方法。
(3)初步掌握使用类和对象编制C++程序。
(4)掌握对象数组、对象指针和string类的使用方法。
(5)掌握使用对象、对象指针和对象引用作为函数参数的方法。
(6)掌握类对象作为成员的使用方法。
(7)掌握静态数据成员和静态成员函数的使用方法。
(8)理解友元的概念和掌握友元的使用方法。
1.2实验内容和步骤
1.输入下列程序
//test4-1.cpp
#include
usingnamespacestd;
classCoordinate
{public:
Coordinate(intx1,inty1)
{x=x1;
y=y1;
}
Coordinate(Coordinate&p);
~Coordinate()
{cout<<”Destructoriscalleded\n”;}
intgetx()
{returnx;}
intgety()
{returny;}
private:
intx,y;
};
Coordinate:
:
Coordinate(Coordinate&p)
{x=p.x;
y=p.y;
cout<<”copy-initializationConstructouiscalled\n”;
}
intmain()
{Coordinatep1(3,4);
Coordinatep2(p1);
Coordinatep3=p2;
cout<<”p3=(“<return(0);
}
(1)写出程序的运行结果。
copy-initializationConstructouiscalled
copy-initializationConstructouiscalled
p3=(3,4)
Destructoriscalleded
Destructoriscalleded
Destructoriscalleded
Pressanykeytocontinue
(2)将Coordinate类中带有两个参数的构造函数进行修改,在函数体内增添下述语句:
cout<<”Constructoriscalled.\n”;
写出程序的运行结果,并解释输出结果。
copy-initializationConstructouiscalled
copy-initializationConstructouiscalled
p3=(3,4)
Constructoriscalled.
Destructoriscalleded
Destructoriscalleded
Destructoriscalleded
Pressanykeytocontinue
(3)按下列要求进行调试:
在主函数体内,添加下列语句:
Coordinatep4;
Coordinatap5
(2);
调试程序时会出现什么错误?
为什么?
如何对已有的构造函数进行适当修改?
P4里面没有参数,不符合Coordinate关于类的定义;p5的参数只有一个,也不符合不知道是赋给x还是y;在p4和p5中都各加两个参数;如:
p4(2,3);p5(3,4);
(4)经过以上第
(2)步和第(3)步的修改后,结合运行结果分析:
创建不同的对象时会调用不同的构造函数。
2.设计一个4*4魔方程序,让魔方的各行值的和等于各列值的和,并且等于两对角线值的和。
例如一下魔方:
313525
9211915
17131123
727291
各行、各列以及对角线值的和都是64.
【提示】
求4*4魔方的一般步骤如下:
(1)设置初始魔方的起始值和相邻元素之间的差值。
例如上述魔方的初始魔方的起始值(first)和相邻元素之间的差值(step)分别为:
first=1
step=2
(2)设置初始魔方元素的值。
例如上述魔方的初始魔方为:
1357
9111315
17192123
25272931
(3)生成最终魔方。
方法如下:
求最大元素值与最小元素值的和sum,该实例的sum是:
1+31=32
用32减去初始魔方所有对角线上元素的值,然后将结果放在原来的位置,这样就可求得最终魔方。
本例最终魔方如下:
313525
9211915
17131123
727291
本题的魔方类magic的参考框架如下:
classmagic
{public:
voidgetdata();
voidsetfirstmagic();
voidgeneratemagic();
voidprintmagic();
private:
intm[4][4];
intstep;
intfirst;
intsum;
};
3.设计一个用来表示直角坐标系的Location类,在主程序中创建类Location的两个对象A和B,要求A的坐标点在第3象限,B的坐标在第2象限,分别采用成员函数和友元函数计算给定两个坐标点之间的距离,要求按如下格式输出结果:
A(x1,y1),B(x2,y2)
Distance1=d1
Distance1=d2
其中:
x1、x2、y1、y2为指定的坐标值,d1和d2为两个坐标点之间的距离。
【提示】
类Location的参考框架如下:
classLocation{
public:
Location(double,double);
doubleGetx()
doubleGety()
doubledistance(Location&);
frienddoubledistance(Location&,Location&);
private:
doublex,y;
};
【【【#include"iostream.h"
#include"math.h"
classLocation{
private:
intx,y;
public:
Location(inti,intj):
x(i),y(j){}
intGetx(){returnx;}
intGety(){returny;}
doubledistance(Locationb);
frienddoubledistance(Location&a,Location&b);
};
doubledistance(Location&a,Location&b)//友元函数
{intdx=a.x-b.x;
intdy=a.y-b.y;
returnsqrt(dx*dx+dy*dy);}
doubleLocation:
:
distance(Locationb)//成员函数
{intdx=x-b.x;
intdy=y-b.y;
returnsqrt(dx*dx+dy*dy);}
voidmain()
{
LocationA(-10,-20),B(-40,60);
cout<<"A("<doubled=A.distance(B);//调用成员函数
cout<<"Distance1="<cout<<"Distance2="<】】】
4.声明一个Student类,在该类中包括一个数据成员score(分数)、两个静态数据成员total_score(总分)和count(学生人数);还包括一个成员函数account()用于设置分数、累计学生成绩之和、累计学生人数,一个静态成员函数sum()用于返回学生的成绩之和,另一个静态成员函数average()用于求全班成绩的平均值。
在main函数中,输入某班同学的成绩,并调用上述函数求出全班学生的成绩之和和平均分。
5.使用C++的string类,将5个字符串按逆转后的顺序显示出来。
例如,逆转前的5个字符串是:
GermanyJapanAmericaBritainFrance
按逆转后的顺序输出字符串是:
FranceBritainAmericaJapanGermany
实验2派生类与继承
2.1实验目的和要求
(1)掌握派生类的声明方法和派生类构造函数的定义方法。
(2)掌握不同继承方式下,基类成员在派生类中的访问属性。
(3)掌握在继承方式下,构造函数与析构函数的执行顺序与构造规则。
(4)学习虚基类在解决二义性问题中的作用。
2.2实验内容与步骤·
1.输入下列程序。
//test4_1.cpp
#include
usingnamespacestd;
classBase{
public:
voidsetx(inti)
{x=i;}
Intgetx()
{returnx;}
public:
intx;
};
classDerived:
publicBase{
public:
voidsety(inti)
{y=i;}
intgety()
{returny;}
voidshow()
{cout<<”Base:
:
x=”<}
public:
inty;
};
intmain()
{Derivedbb;
bb,setx(16);
bb.sety(25);
bb.show();
cout<<”Base:
:
x=”<cout<<”Derived:
:
y=”<cout<<”Base:
:
x=”<cout<<”Derived:
:
y=”<return0;
}
(1)
写出程序的运行结果。
(2)按以下要求,对程序进行修改后再调试,指出调试中出错的原因。
将基类Base中数据成员x的访问权限改为private时,会出现哪些错误?
为什么?
将基类Base中数据成员x的访问权限改为protected时,会出现哪些错误?
为什么?
在源程序的基础上,将派生类Derived的继承方式改为private时,会出现哪些错误?
为什么?
在源程序的基础上,将派生类Derived的继承方式改为protected时,会出现哪些错误?
为什么?
2.编写一个学生和教师的数据输入和显示程序。
学生数据有编号、姓名、性别、年龄、系别和成绩,教师数据有编号、姓名、性别、年龄、职称和部门。
要求将编号、姓名、性别、年龄的输入和显示设计成一个类Person,并作为学生类Student和教师类Teacher的基类。
供参考的类结构如下:
classPerson{
...
};
classStudent:
publicPerson{
...
};
classTeacher:
publicPerson{
...
};
3.按要求阅读、编辑、编译、调试和运行以下程序。
(1)阅读、编辑、编译、调试和运行以下程序,并写出程序的运行结果。
//test4_3_1.cpp
#include
#include
usingnamespacestd;
classMyArray{
public:
MyArray(intleng);
~MyArray{};
voidInput();
voidDisplay(string);
protected:
int*alist;
intlength;
};
MyArray:
:
MyArray(intleng)
{if(leng<=0)
{cout<<”errorlength”;
exit
(1);
}
alist=newint[leng];
length=leng;
if(alist==NULL)
{cout<<”assignfailure”;
exit
(1);
}
cout<<”MyArray类对象已创建。
”<}
MyArray:
:
~MyArray()
{delete[]alist;
cout<<”MyArray类对象被撤销。
”<}
voidMyArray:
:
Display(stringstr)
{inti;
int*p=alist;
cout<“;
for(i=0;icout<<*p<<””;
cout<}
voidMyArray:
:
Input{}
{cout<<”请键盘输入”<”;
inti;
int*p=alist;
for(i=0;icin>>*p;
}
intmain()
{MyArraya(5);
a.Input();
a.Display(“显示已输入的”);
return0;
}
(2)声明一个类SortArray继承类MyArray,在该类中定义一个函数,具有将输入的整数从小到大进行排序的功能。
【提示】
在第
(1)步的基础上可增加下面的参考框架:
classSortArray:
publicMyArray{
public:
voidSort();
SortArray(intleng):
MyArray(leng)
{cout<<”SortArray类对象已创建。
”<}
virtual~SortArray();
};
SortArray:
:
~SortArray()
{cout<<”SortArray类对象被撤销。
”<}
voidSortArray:
:
Sort()
{
//请自行编写Sort函数的代码,将输入的整数从小到大排序。
}
//并将主函数修改为:
intmain()
{SortArraya(5);
s.Input();
s.Display(“显示排序以前的”);
s.Sort();
s.Display(“显示排序以后的”);
return0;
}
声明一个类ReArray继承类MyArray,在该类中定义一个函数,具有将输入的整数进行倒置的功能。
【提示】
在第
(1)步的基础上可增加下面的参考框架:
ClassReArray:
publicMyArray{
Public:
Voidreverse();
ReArray(intleng);
Virtual~ReArray();
};
请读者自行编写构造函数、析构函数和倒置函数ReArray,以及修改主函数。
(3)声明一个类AverArray继承类MyArray,在该类中定义一个函数,具有求输入的整数平均值的功能。
【提示】
在第
(1)步的基础上增加下面的参考框架:
classAverArray:
publicMyArray{
Public:
AverArray(intleng);
~AverArray();
DoubleAver();
};
请读者自行编写构造函数、析构函数和求平均值函数Aver(求解整数的平均值),以及修改主函数。
(2)声明一个NewArray类,同时继承了类SortArray,ReArray和AverArray,使得类NewArray的对象同时具有排序、倒置和求平均值的功能。
在继承的过程中声明MyArray为虚基类,体会虚基类在解决二义性问题中的作用。
实验3多态性
3.1实验目的和要求
(1)了解多态性的概念。
(2)掌握运算符重载的基本方法。
(3)掌握虚函数的定义和使用方法。
(4)掌握纯虚函数和抽象类的概念和用法。
3.2实验内容与步骤
1.分析并调试下列程序,写出程序的输出结果,并解释输出结果。
//test5_1.cpp
#include
usingnamespacestd;
classB{
public:
virtualvoidf1(doublex)
{cout<<”B:
:
f1(double)”<}
voidf2(doublex)
{cout<<”B:
:
f2(double)”<<2*x<}
voidf3(doublex)
{cout<<”B:
:
f3(double)”<<3*x<}
}
classD:
publicB{
public:
virtualvoidf1(doublex)
{cout<<”D:
:
f1(double)”<}
voidf2(doublex)
{cout<<”D:
:
f2(double)”<<2*x<}
voidf3(doublex)
{cout<<”D:
:
f3(double)”<<3*x<}
};
intmain()
{Dd;
B*pb=&d;
D*pd=&d;
pb->f1(1.23);
pb->f1(1.23);
pb->f2(1.23);
pb->f3(1.23);
pb->f3(3.14);
return0;
}
2.编写一个程序,其中设计一个时间类Time,用来保存时、分、秒等私有数据成员,通过重载操作符“+”实现两个时间的相加。
要求将小时范围限制在大于等于0,分钟范围限制在0~59,秒钟范围限制在0~59秒。
【提示】
时间类Time{
public:
Time(inth=0,intm=0,ints=0);
Timeoperator+(Time&);
voiddisptime(string);
private:
inthourse;
intminutes;
intseconds;
};
3.给出下面的抽象基类container;
classcontainer
{
protected:
doubleradius;
public:
container(doubleradius1);
virtualdoublesurface_area()=0;
virtualdoublevolume()=0;
};
要求建立3个继承container的派生类cube、sphere与cylinder,让每一个派生类都包含虚函数surface_area()和volume(),分别用来计算正方体、球体和圆柱体的表面积及体积。
要求写出主程序,应用C++的多态性,分别计算边长为6.0的正方体、半径为5.0的球体,以及半径为5.0和高为6.0的圆柱体的表面积和体积。
4.编写一个程序,用于进行集合的并、差和交运算。
例如输入整数集合{954367}和{2469},计算出它们进行集合的并、差和交运算后的结果。
【提示】
i.可用以下表达式实现整数集合的基本运算:
s1+s2两个整数集合的并运算
s1-s2两个整数集合的差运算
s1*s2两个整数集合的交运算
ii.参考以下Set类的框架,用于完成集合基本运算所需的各项功能。
classset{
public:
set:
:
set();
voidset:
:
input(intd);
intset:
:
length();
intset:
:
getd(inti);
voidset:
:
disp();
setset:
:
operator+(sets1);
setset:
:
operator-(sets1);
setset:
:
operator*(sets1);
setset:
:
operator=(sets1);
protected:
intlen;
ints[MAX];
};
实验4运算符重载和类模板
一、实验目的
1.掌握C++中运算符重载的机制和运算符重载的方式;
2.掌握类型转换的方式、内存的动态分配;
3.掌握类模板的定义,掌握类模板的实例化。
二、知识要点
1.运算符重载
成员函数方式:
单目(返回类型类名∷operator单目运算符())
双目(返回类型类名∷operator双目运算符(类名&引用))
下标运算符重载:
类型类名∷operator[](下标类型形参)
{
函数体
}
提取符重载:
预定义插入符
ostream&ostream∷operator<<(type&obj);
预定义提取符
istream&istream∷operator>>(type&obj);
运算符重载规则:
(1)不可以重载非C++的运算符;
(2)运算符重载可以采用成员函数方式或友元方式;
(3)被重载的运算符必须保持预定义的的优先级与结合性;
(4)应尽量使重载的运算符语义自然、好理解;
(5)注意各运算符之间的联系。
2.类模板:
template
class类名
{…};
(1)每一个类模板的成员函数的外部定义,都与一般函数模板的定义一
样,必须以类型形参开始,此外还应加以函数返回值类型、类范围、函数名、
形参序列,类名后面必须加上类型形参。
(2)类模板是类的抽象类型,它的实例化是生成一个具体的类。
三、实验内容及步骤
1.分析教程“函数模板”中的例子,自行设计一个简单的类模板。
2.分析教程“运算符重载”中的例子,自行设计一个简单的重载运算符。
3.指出下面程序中的错误,改正并运行。
#include
classPoint{
private:
intx1,x2;
public:
Point(intx,inty){x1=x;x2=y;}
intx_cord(){returnx1;}
inty_cord(){returnx2;}
}
main()
{
Pointdata(5,6);
cout<cout<Pointmore_data[20];
}
实验5文件操作
一、实验目的
1.掌握基本的输入输出操作及格式;
2.用C++预定义的文件I/O类进行文件输入输出。
二、知识要点
文件操作:
打开文件、读写文件、关闭文件。
低层次I/O机制:
intcreat()、intopen()、intclose