class CBase1
{
int x;
public:
CBase1()
{x=0;cout<<"调用构造函数CBase1()!\\n";}
CBase1(int a)
{x=1;cout<<"调用构造函数CBase1(int)!\\n";}
~CBase1(){cout<<"调用析构函数~CBase1()!\\n";}
};
class CBase2
{int y;
public:
CBase2()
{y=0;cout<<"调用构造函数CBase2()!\\n";}
CBase2(int a)
{y=a;cout<<"调用构造函数CBase2(int)!\\n";}
~CBase2(){cout<<"调用析构函数~CBase2()!\\n";}
};
class A
{int x;
public:
A(){x=0;cout<<"调用构造函数A()!\\n";}
A(int a){x=a;cout<<"调用构造函数A(int)!\\n";}
~A(){cout<<"调用析构函数~A()!\\n";}
};
class CDerived:public CBase1,virtual public CBase2
{
A a;
public:
CDerived()
{cout<<"调用构造函数CDerived()!\\n";}
CDerived(int x,int y,int z):a(x),CBase1(y),CBase2(z)
{cout<<"调用构造函数CDerived(int,int,int)!\\n";}
~CDerived(){cout<<"调用析构函数~CDerived()!\\n";}
};
void main()
{
CDerived *x=new CDerived;
CDerived y(2,3,4);
delete x;
cout<<"main()函数结束!\\n";
}
实验结果:
2.2编写并调试程序:
1)定义一个图形类,其中有保护类型的成员数据:高度和宽度,一个公有的构造函数。由该图形类建立两个派生类:矩形类和等腰三角形类。在每个派生类中都包含一个函数area(),分别用来计算矩形和等腰三角形的面积。
1.程序设计如下:
#includeclass picture
{
protected:
double h,w;
public:
picture (double i,double j){h=i;w=j;}
};
class jpicture:public picture
{double mi;
public:
};
class sanjiaoxing:public picture
{
double mi;
public:
};
void main()
{ jpicture a(1,2);
sanjiaoxing b(3,4);
a.area();
b.area();
}
2.实验结果:
2)定义一个人员类cpeople,其属性有(保护类型):姓名、性别、年龄;从中派生出学生类cstudent,添加属性:学号、入学时间和入学成绩;从cpeople类再派生出教师类cteacher,添加属性:职务、部门、工作时间;有cstudent类派生研究生类cgraduate,添加属性:研究方向和导师,由cgraduate和cteacher共同派生出在职研究生类cgradonwork,分别定义其中的构造函数和输出函数。主函数中定义各种类的对象,并完成测试。
1.程序设计如下:
2.实验结果:
3、实验结论:
实验十 运算符重载
1. 实验目的及要求
1) 掌握运算符重载的基本概念和方法。
2) 熟习几种特殊的运算符的重载。
2. 实验内容
1. 分析下面的程序,指出程序运行的结果:
#includeclass point{
int x,y;
public:
point(int vx,int vy){
x=vx; y=vy;}
point(){x=0,y=0;}
point operator+(point p1)
{
int px=x+p1.x;
int py=y+p1.y;
return point(px,py);
}
point operator-(point p1)
{
point p;
int px=x-p1.x;
int py=y-p1.y;
return point(px,py);
}
void print(){cout<};void main(void)
{
point p1(10,10),p2(20,20);
p1=p1+p2;
p1.print();
//p2.print();
//p3.print();
}
程序分析:
运行结果为:
3) 分析下面程序,指出程序运行的结果:
#includestatic int dys[]={31,28,31,30,31,30,31,31,30,31,30,31};
class date
{
int mo,da,yr;
public:
date(int m,int d,int y){mo=m;da=d;yr=y;}
date(){}
void disp()
{cout< date operator+(int day) {
date dt=*this;
day+=dt.da;//cout< while(day>dys[dt.mo-1]) {day-=dys[dt.mo-1];//cout< if(++dt.mo==13) {dt.mo=1;
dt.yr++;
}
}
//cout< //dt.disp(); dt.da=day;
return dt;
}
};
void main(void)
{
date d1(5,31,2009),d2;
//d1.disp();
d2=d1+20;
d2.disp();
}
程序运行结果:
三. 编写并调试程序.
定义一个描述平面上一个点的类point,重载“++”和“--”运算符,并区分这两种运算符的前置和后置操作,构成一个完整的程序。
程序代码:
程序运行的结果是:
2)构造一个分数类rationalNumber,该类中包括分子和分母两个成员数据,并具有下述功能:
1建立构造函数,它能防止分母为0,当分数不是最简形式时进行约分,并避免分母为负数。
2重载加法、减法、乘法和除法运算符。
3重载关系运算符:>、<、==等。
程序代码:
程序执行的结果为:
实验十一 虚函数
一、实验目的
1)掌握虚函数的定义和使用
2)掌握抽象类的定义和使用
3)掌握纯虚函数的定义
4)掌握虚析构函数、纯虚函数和抽象类的作用
二、实验原理
1.利用虚函数的作用:当编译器编译虚函数时,编译系统将用动态连接的方式进行编译。即在编译时不确定该虚函数的版本,而是利用一种机制在运动过程中根据其所指向的实例决定使用哪一个函数版本。
2.利用虚析构函数的原则:当将基类指针或引用new运算符指向派生类对象时,为了在释放派生类对象时能调用派生类的析构函数,必须将基类的析构函数定义为虚函数。
3.抽象类的作用:为它的所有派生类提供一个公共接口,纯虚函数是定义抽象类的一种间接手段。
三、实验设备
实验室里调备的计算机、window xp,visual c++6.0
四、实验内容
4.1分析下面各题程序,按各题的要求进行实验
1)分析下面的程序,指出程序运行的结果:
#includeclass CBase
{public:
virtual void f1() //将成员函数f1()声明为虚函数
{cout<<"调用函数CBase::f1()!"< virtual void f2() //将成员函数f2()声明为虚函数 {cout<<"调用函数CBase::f2()!"< void f3() //一般成员函数 {cout<<"调用函数CBase::f3()!"<};class CDerived:public CBase //公有继承CBase
{void f1()
{cout<<"调用函数CDerived::f1()!"<void f2(){cout<<"调用函数CDerived::f2()!"<void f3(){cout<<"调用函数CDerived::f3()!"<};void main()
{CBase obj1,*p; //定义CBase的对象obj1和指针对象p
CDerived obj2; //定义CDerived的对象obj1
p=&obj1; //将obj1的地址给p
p->f1(); //通过p调用基类版本的f1()函数
p->f2(); //通过p调用基类版本的f2()函数
p->f3(); //通过p调用基类版本的f3()函数
p=&obj2; //将派生类对象obj2的地址赋给p
p->f1(); //动态连接,调用派生类版本
p->f2(); //动态连接,调用派生类版本
p->f3(); // 调用基类版本
}
运行的结果:
2)分析下面的程序,指出程序运行的结果:
#includeclass CBase
{public:
CBase() //CBase类的构造函数
{cout<<"调用构造函数CBase()!"< fun();} //构造函数中调用虚函数fun() virtual void fun() //定义虚函数
{cout<<"调用构造函数CBase::fun()!"<};class CDerived:public CBase
{public:
CDerived() //CDerived类的构造函数
{cout<<"调用构造函数CDerived()!"< fun();} //构造函数中调用虚函数fun() void fun()
{cout<<"调用构造函数CDerived::fun()!"<};void main()
{CDerived d; //创建对象
d.fun();
}
运行结果:
3)分析下面的程序,指出程序的错误
#include#includeclass CBase
{protected:
char *ch;
public:
CBase(char *x)
{ch=new char[20];
strcpy(ch,x);
}
virtual void fun()=0;
virtual void fun1() //虚函数
{cout< {cout< ~CBase() {delete[]ch; cout<<"~CBase()"< }};
class CDerived:public CBase
{protected:
char *ch;
public:
CDerived (char *x,char*y):CBase(y)
{ch=new char[20];
strcpy(ch,x);}
void fun1()
// {cout< {cout< Virtual ~CDerived() {delete[]ch; cout<<"~CDerived()"<};void main()
{CBase obj1("Hello"),*p;
p=&obj1;
p->fun1();
p->fun();
p=new CDerived("China
p->fun1();
p->fun();
delete p;
}
运行结果:
4.2编写并调试程序
1)编写一个程序计算三角,正方形和圆形的面积。
分析:依题意,可以抽象出一个基类CBase,在其中说明一个虚函数,用来求面积,并利用单接口、多实现版本设计各个图形求面积的方法。
源程序:
运行结果:
2)编写一个程序计算正方形、球体和圆柱体的表面积和体积。
分析:依题意,抽象出一个公共基类CContaineer为抽象类,在其中定义求表面积和体积的虚函数(该抽象类本身没有表面积和体积可言)。抽象类中定义一个公共的数据成员radius,此数据可作为球体的半径、正方形的边长、圆柱体底面积圆半径。由此抽象类派生出要描述的三个类,在这三个类中都具有求表面积和体积的重定义版本。
源程序:
运行结果:
实验总结:
实验十二 函数模板与类模板
一、实验目的
1.理解模板的作用。
2. 学习函数模板及其声明方法
3. 掌握模板函数及其生成方法
4. 学习函数模板的异常情况的处理方法
5. 学习类模板的定义和使用方法
二、实验内容
2.1分析下面各题程序,按各题的要求进行实验
1)分析下面的程序,指出程序运行的结果:
教材p239 6.7题
运行结果:
2)改错:教材p239 6.7题
2.2编写并调试程序
1)教材p242 6.12题。
提示10个元素的整数数组的冒泡排序算法如下:
int a[10];
int temp;
for(int i=0;i<10;i++)
for(int j=0;i<10-i;j++)
if( a[j]>a[j+1])
{ temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
2)用类模板实现对栈的操作,栈的数据结构由链表实现。栈的功能:进栈、出栈和清空。并在主函数中实现对int栈和struct CHAP5型栈的基本操作。
Struct CHAP5
{
Char * pName;
Bool Gender;
int Age;
Struct CHAP5 * next;
}
提示:参考教材例题6.7.
源程序:
运行结果:
实验总结:
实验十三 I/O流类库
1.实验目的
1)熟悉流及流类库的作用。
2)掌握流类库常用的类及其成员函数的使用方法
3)学习输入输出基本方法及其格式控制
4)学习文本文件和二进制文件的输入输出方法
2.实验要求:
(1)设计一个留言类,实现如下功能:
1)程序第一次运行时,建立一个文本文件c:\\msg.ini,并把用户输入的信息存入该文件。
2)以后运行时,先读取文件的内容并显示给用户,然后由用户使入新的信息,退出时存入文档。文件的内容,既可以是最新的,也可以包括以前的信息,请自己选择。
(2)定义一个类,重载输出运算符“<<”,用一定的格式将类的成员显示出来。
3.实验内容:
(1)定义一个类Mailman,在构造函数中检查“c:\\msg.ini”文件的存在,如果不存在则创建之,否则读取并显示内容给用户。C++库函数:
Open(“c:\\msg.ini” ,ios::in);
用法: fstream fs;
fs. Open(“c:\\msg.ini” ,ios::in);
参考程序:
Void MailMan::ReadMsgFromFile()
{
fs. open(“c:\\msg.ini” ,ios::in);
char temp;
fs.unsetf(ios::skipws); //读入空格
for(int i=0;i<1024;i++)
{
if(fs>>temp) //读入一个字符,否则返回false
{
Buf[i]=temp;
}
Else
{ Buf[i]=’\0’;
Break;
}
}
Fs.close();
}
(2)把用户输入的信息存放到程序中定义的缓冲区,请注意缓冲区的大小。
Void MailMan::InMsg()
{
Char temp;
Cin.unsetf(ios::skipws);
Cout<<”\\n please input your message, end with \”~\”(shift+`“<for(int i=0;i<1024;i++){
Cin>>temp;
Buf[i]=temp;
if(temp==”~”) //读入一个字符,直到~位置
{
Buf[i]=’\0’;
Break;
}
}
}
(3)用户退出时,询问是否把留言写入,如果是则把信息写入文件:
Void MailMan::SaveMsgToFile()
{
fs. open(“c:\\msg.ini” ,ios::out);
fs<fs.close();cout<<”\\n message saved to file.”<return;}
(4)定义一个类abc,并重载输出运算符,使得abc类的成员可以以多种样式输出。
Class abc
{
int i;
double d;
float f;
public:
abc();
friend ostream & operator<<(ostream & s,abc x);
};
abc::abc()
{
i=9999;
d=-100.101;
f=9.0;
}
ostream & operator<<(ostream & s,abc x)
{
cout.setf(ios:;hex);
cout<cout. unsetf(ios:;hex);cout.width(15);
cout. setf(ios:;fixed);
cout.precision(6);
cout.fill(‘$’);
cout<cout.width(20);cout.fill(‘@’);
cout.precision(4);
cout.setf(ios::showpos);
cout<return s;}
在main()函数中,定义一个abc类的对象e之后,只需用一下语句便可以用自定义的格式输出abc类的对象:
abc e;
cout<完整程序:运行结果:
总验总结: