资源描述
实验一 类和对象的基本操作
实验目的:
l 掌握定义类、实现类的方法;
l 领会面向对象程序设计的基本思想和方法;
实验内容:
l 在多个程序文件中实现类的定义及对象的使用
实验步骤:
1、实例一
在计算机中处理数据有时是无限的,例如在平面中的角度在0°-359°之间,如果在359°上再加1°,则角度变成0°,同样,从0°再减1°,则成为359°。类似的还有星期、月份等,我们设计一个通用的循环计数器类,能够设置循环计数器的起止范围,并进行基本操作。
(1)头文件
此文件中声明循环计数器类。
//文件crinum.h
#ifndef __CN
#define __CN
class Circular_Number
{
public:
void set_mode(int,int);//设置循环计数器的上下界
void set_value(int);//设置循环计数器的当前值
int get_value();//取循环计数器的当前值
void increment();//累加循环计数器
void decrement();//累减循环计数器
private:
int min_val;//最小值
int max_val;//最大值
int current;//当前值
};
#endif
(2)循环计数器类的实现文件
//文件cirnum.cpp
#include"cirnum.h"
void Circular_Number::set_mode(int min,int max)
{
min_val=(min<=max)?min:max;
max_val=(min<=max)?max:min;
}
void Circular_Number::set_value(int value)
{
if(value<min_val) current=min_val;
else
{
if(value>max_val)current=max_val;
else current=value;
}
}
int Circular_Number::get_value()
{
return current;
}
void Circular_Number::increment()
{
int mode=max_val-min_val+1;
current=((current-min_val)+1)%mode+min_val;
}
void Circular_Number::decrement()
{
int mode=max_val-min_val+1;
current=((current-min_val)-1+mode)%mode+min_val;
}
(3)应用文件
//文件test.cpp
#include<iostream.h>
#include"cirnum.h"
void main()
{
int loop;
Circular_Number angle; //角度循环计数器
Circular_Number month; //月份循环计数器
angle.set_mode(0,359);
angle.set_value(200);
month.set_mode(1,12);
month.set_value(9);
cout<<"the initial angle is "<<angle.get_value()<<endl;
cout<<"the initial month is "<<month.get_value()<<endl;
for(loop=1;loop<=100;loop++)angle.increment();
cout<<"the current angle is "<<angle.get_value()<<endl;
for(loop=1;loop<=300;loop++)angle.decrement();
cout<<"the current angle is "<<angle.get_value()<<endl;
for(loop=1;loop<=10;loop++)month.increment();
cout<<"the current month is "<<month.get_value()<<endl;
for(loop=1;loop<=15;loop++)month.decrement();
cout<<"the current month is "<<month.get_value()<<endl;
}
2、实例二
我们设计一个简单日期类,其中包含月、日、年,并能够进行判断是否闰年、设置日期等基本操作。
(1)头文件
//文件Tdate.h
class Tdate
{
public:
void Set(int m, int d, int y);
int IsLeapYear();
void Print();
private:
int month;
int day;
int year;
};
(2)实现文件
//文件Tdate.cpp
#include<iostream.h>
#include"Tdate.h"
void Tdate::Set(int m, int d, int y)
{
month=m;
day=d;
year=y;
}
int Tdate::IsLeapYear()
{
return (year%4==0 && year%100!=0) || (year %400==0);
}
void Tdate::Print()
{
cout<<month<<"/"<<day<<"/"<<year<<endl;
}
(3)应用程序
#include"Tdate.h"
void main(){
Tdate a;
a.Set(3,18,2001);
a.Print();
}
3、思考问题
(1)面向对象程序设计方法相对于过程化程序设计方法的优势有哪些;
(2)为什么类可以实现数据封装和信息隐藏;
(3)用设置函数来给数据成员进行设置值是否合理;
(4)我们自己设计的类本质上是什么;
实验报告设计内容
实验内容
定义一个MyDate类,其中成员有:
1、包含三个私有数据成员year、month、day。
2、公有成员函数及其功能描述如下:
(1)有默认值的构造函数。
(2)更改年月日成员函数
(3)更改年成员函数
(4)更改月成员函数
(6)更改年成员函数
(7)获取年值成员函数
(8)获取月值成员函数
(9)获取中文月值成员函数
(10)获取日值成员函数
(11)显示日期成员函数
(12)判断闰年成员函数
实验二 类成员的基本操作
实验目的:
l 理解在面向对象程序设计中构造函数所处的地位和作用;
l 掌握构造函数和析构函数的使用方法;
l 理解构造函数重载的必要性;
l 理解使用拷贝构造函数的需要性及深拷贝与浅拷贝的不同;
l 掌握定义和使用拷贝构造函数的方法;
l 理解为什么要使用静态成员及其用法;
实验内容:
l 编制一个类,并在其中编制多种构造函数和析构函数来更好地理解构造的方法与析构的次序;
l 在类中编制拷贝构造函数,
l 用静态数据成员实现链表的操作。
l 用静态函数成员实现链表的操作查找操作。
实验步骤:
1、实例一
我们用上次实验中的循环计数器为例,其带构造函数的实现如下。
(1)头文件
//crinum.h
class Circular_Number
{
public:
Circular_Number(int min,int max,int value);
int get_value();//取循环计数器的当前值
void increment();//累加循环计数器
void decrement();//累减循环计数器
~Circular_Number();
private:
int min_val;//最小值
int max_val;//最大值
int current;//当前值
};
(2)实现文件
//crinum.cpp
#include"cirnum.h"
Circular_Number::Circular_Number(int min,int max,int value)
{
min_val=(min<=max)?min:max;
max_val=(min<=max)?max:min;
if(value<min_val) current=min_val;
else
{
if(value>max_val)current=max_val;
else current=value;
}
cout<<"construct Circular_Number"<<endl;
}
int Circular_Number::get_value()
{
return current;
}
void Circular_Number::increment()
{
int mode=max_val-min_val+1;
current=((current-min_val)+1)%mode+min_val;
}
void Circular_Number::decrement()
{
int mode=max_val-min_val+1;
current=((current-min_val)-1+mode)%mode+min_val;
}
Circular_Number::~Circular_Number()
{
cout<<"destruct Circular_Number"<<endl;
}
(3)应用程序
#include<iostream.h>
#include"cirnum.h"
void main()
{
int loop;
Circular_Number angle(0,359,200); //角度循环计数器
Circular_Number month(1,12,9); //月份循环计数器
cout<<"the initial angle is "<<angle.get_value()<<endl;
cout<<"the initial month is "<<month.get_value()<<endl;
for(loop=1;loop<=100;loop++)angle.increment();
cout<<"the current angle is "<<angle.get_value()<<endl;
for(loop=1;loop<=300;loop++)angle.decrement();
cout<<"the current angle is "<<angle.get_value()<<endl;
for(loop=1;loop<=10;loop++)month.increment();
cout<<"the current month is "<<month.get_value()<<endl;
for(loop=1;loop<=15;loop++)month.decrement();
cout<<"the current month is "<<month.get_value()<<endl;
}
2、实例二
现在需要在屏幕上模拟数字式时钟的动作,显示时间格式为hh:mm:ss。
我们利用前面的循环计数器来作为类型,设置hour、minute、second,并编写clock类,在此类中完成时间格式的输出、时间的刷新功能。
(1)头文件
//crinum.h
同上。
//clock.h
#include"cirnum.h"
class clock
{
public:
clock(int h,int m,int s);
void update();
void show();
~clock();
private:
Circular_Number hour;
Circular_Number minute;
Circular_Number second;
};
(2)实现文件
//crinum.cpp同上。
//clock.cpp
#include"clock.h"
#include<iostream.h>
clock::clock(int h,int m,int s):hour(0,23,h),minute(0,59,m),second(0,59,s)
{
cout<<"construct clock"<<endl;
}
void clock::update()
{
second.increment();
if(second.get_value()==0)
{
minute.increment();
if(minute.get_value()==0)hour.increment();
}
}
void clock::show()
{
cout<<hour.get_value()<<":"<<minute.get_value()<<":"<<second.get_value()<<endl;
}
clock::~clock(){ cout<<"destruct clock"<<endl; }
(3)应用程序
#include<iostream.h>
#include"clock.h"
void main()
{
int loop;
clock rolex(4,15,30);
clock cima(14,0,0);
cout<<"Rolex:\n";
for(loop=1;loop<=100;loop++)
{
rolex.update(); rolex.show();
}
cout<<"Cima:\n";
for(loop=1;loop<=100;loop++)
{
cima.update(); cima.show();
}
}
3、实例三
编写一个平面中的点类,一个矩形类,矩形类中的数据成员是点类的对象,在应用程序中移动点,旋转矩形。此例中涉及到了以对象作参数传递及对象作返回值,我们用浅拷贝的方式来完成,即用系统提供的拷贝构造函数。
(1)头文件
//point.h
#include<math.h>
#ifndef __POINT
#define __POINT
class Point{
public:
Point(double ix=3, double iy=4){
x=ix;
y=iy;
cout<<"it is in point constructor."<<endl;
}
double& xoffset(){return x;}
double& yoffset(){return y;}
~Point()
{
cout<<"it is in point destructor."<<endl;
}
private:
double x;
double y;
};
#endif
//rectangle.h
#include<iostream.h>
#include"point.h"
class Rectangle
{
private:
Point topLeft;
Point bottomRight;
public:
Rectangle(double x1,double y1,double x2,double y2)
:topLeft(x1,y1),bottomRight(x2,y2)
{
cout<<"it is rectangle constructor. and the topleft is ("
<<x1<<","<<y1<<"), the bottomright is ("
<<x2<<","<<y2<<")"<<endl;
}
Point TopLeft(){return topLeft;}
Point BottomRight(){return bottomRight;}
Rectangle(Point tl, Point br):topLeft(tl),bottomRight(br)
{
cout<<"it is in the second constructor."<<endl;
}
double area()
{
return (bottomRight.xoffset()-topLeft.xoffset())
*(bottomRight.yoffset()-topLeft.yoffset());
}
void print()
{
cout<<"current rectangle is: ("
<<topLeft.xoffset()<<","<<topLeft.yoffset()<<")";
cout<<"to ("<<bottomRight.xoffset()<<","
<<bottomRight.yoffset()<<")"<<endl;
}
~Rectangle()
{
cout<<"it is in rectangle destructor."<<endl;
}
};
(2)应用程序
#include"rectangle.h"
#include<iostream.h>
Point move(Point p,double ix,double iy)
{
p.xoffset()+=ix;
p.yoffset()+=iy;
return p;
}
Rectangle tranpose(Rectangle R)
{
double x1,y1,x2,y2;
x1=R.TopLeft().xoffset();
y1=R.TopLeft().yoffset();
x2=x1+(R.BottomRight().yoffset()-R.TopLeft().yoffset());
y2=y1+(R.BottomRight().xoffset()-R.TopLeft().xoffset());
return Rectangle (x1,y1,x2,y2);
}
void main()
{
Point p1(2,4);
Point p2(10,20);
Rectangle R1(p1,p2);
R1.print();
cout<<"the area of rectangle R1 is :"<<R1.area()<<endl;
p2=move(p2,4,6);
Rectangle R2(p1,p2);
cout<<"the area of rectangle R2 is :"<<R2.area()<<endl;
R2.print();
Rectangle R3=tranpose(R2);
cout<<"the area of rectangle R3 is :"<<R3.area()<<endl;
R3.print();
}
4、实例四
用一个整型数组存储一个大数,每位上用一个小于10大于等于0的数,编写一个类来实现此大数数组,要求数组用指针动态分配,并在构造函数中初始化此大数,编写输出及加法操作。
(1)头文件
//BigNumberArray.h
class BigNumberArray
{
private:
int *n;
public:
BigNumberArray();
BigNumberArray(BigNumberArray &);
void print();
BigNumberArray add(BigNumberArray);
};
(2)实现文件
//BigNumberArray.cpp
#include"BigNumberArray.h"
#include<iostream.h>
#include<stdlib.h>
BigNumberArray::BigNumberArray()
{
n=new int[40];
for(int i=0;i<40;i++) n[i]=rand()%10;
}
BigNumberArray::BigNumberArray(BigNumberArray &B)
{
n=new int[40];
for(int i=0;i<40;i++)n[i]=B.n[i];
}
void BigNumberArray::print()
{
for(int i=0;i<40;i++)cout<<n[i];
cout<<endl;
}
BigNumberArray BigNumberArray::add(BigNumberArray B2)
{
BigNumberArray B3;
int pre=0;
for(int i=39;i>=0;i--)
{
B3.n[i]=(n[i]+B2.n[i]+pre)%10;
pre=(n[i]+B2.n[i]+pre)/10;
}
return B3;
}
(3)应用程序
#include<iostream.h>
#include"BigNumberArray.h"
void main()
{
BigNumberArray b1;
BigNumberArray b2;
b1.print();
b2.print();
BigNumberArray b3=b1.add(b2);
b3.print();
}
5、实例五
编写一个学生类,其中包含一个静态数据成员,用来记录学生人数,并有构造、析构和寻找下一个学生操作。注意其中静态成员初始化的位置。
(1)头文件
//student.h
class Student
{
public:
Student(char *pName="no name");
~Student();
Student &nextStudent();
static int noOfStudents;
private:
char name[40];
};
(2)实现文件
//student.cpp
#include<iostream.h>
#include<string.h>
#include"student.h"
int Student::noOfStudents=0;
Student::Student(char *pName)
{
cout<<"Create one student \n";
strcpy(name,pName);
noOfStudents++;
cout<<noOfStudents<<endl;
}
Student::~Student()
{
cout<<"Destruct one student \n";
noOfStudents--;
cout<<noOfStudents<<endl;
}
Student & Student::nextStudent()
{
noOfStudents++;
return *this;
}
(3)应用程序
#include<iostream.h>
#include"student.h"
void fn1()
{
Student s1; Student s2;
cout<<"it's in fn1 "<<Student::noOfStudents<<endl;
}
void fn2(Student &s)
{
cout<<"it's in fn2 "<<s.nextStudent().noOfStudents<<endl;
}
void main()
{
Student s1("Jordan");
Student s2("YaoMing");
cout<<Student::noOfStudents<<endl;
fn1();
cout<<Student::noOfStudents<<endl;
fn2(s2);
cout<<Student:: noOfStudents <<endl;
}
6、实例六
编写一个学生类,其中包含指针类型的静态数据成员,用来指向链表的首结点,并有静态成员函数,用来查找某个学生是否在链表当中,还要能对整个链表进行遍历。
(1)头文件
//student1.h
class Student
{
public:
Student(char *pName);
~Student();
static Student *findname(char *pName);
void traverse();
private:
static Student *pFirst;
Student *pNext;
char name[40];
};
(2)实现文件
//student1.cpp
#include<iostream.h>
#include<string.h>
#include"student1.h"
Student *Student::pFirst=NULL;
Student::Student(char *pName)
{
strncpy(name,pName,sizeof(name));
name[sizeof(name)-1]='\0';
pNext=pFirst;
pFirst=this;
}
Student::~Student()
{
if(pFirst==this)
{
pFirst=pNext; return;
}
for(Student *pS=pFirst;pS;pS=pS->pNext)
if(pS->pNext==this)
{
pS->pNext=pNext;
return;
}
}
Student *Student::findname(char *pName)
{
for (Student *pS=pFirst;pS;pS=pS->pNext)
if(strcmp(pS->name,pName)==0) return pS;
return (Student *)0;
}
void Student::traverse()
{
for (Student *pS=pFirst;pS;pS=pS->pNext)
{
cout<<pS->name<<endl;
}
}
(3)应用程序
#include<iostream.h>
#include"student1.h"
void f()
{
Student s1("John");
Student s2("Mary");
s2.traverse();
}
void main()
{
Student s1("Randy");
Student s2("Jenny");
Student s3("Kinsey");
s3.traverse();
f();
cout<<"return back from f:"<<endl;
s1.traverse();
Student *pS=Student::findname("Jenny");
if(pS) cout<<"ok."<<endl;
else cout<<"no find."<<endl;
}
实验报告设计内容:
1、模拟加油站工作
在任何时候,应该知道每公斤汽油的价格和油泵所在的油桶中还有多少汽油,当一个加油的请求出现时,如果要求加油的数量少于或等于油桶中的剩余汽油数量,就满足加油请求,否则,只能抽出油桶中所剩余的汽油量。
要求在构造函数中对几个数据成员进行初始化,在显示操作中显示当前数据成员的值,在加油操作中进行加油操作,并显示本次加油量、应付金额及油桶中剩余油量。
2、试编写一个矩阵类并完成矩阵的基本运算。在矩阵类中要有构造函数、拷贝构造函数、析构函数、矩阵的数乘运算、矩阵的加法运算、矩阵的转置运算、矩阵的乘法运算等操作,且矩阵要用动态空间来存储。
实验三 模板类
实验目的:
l 初步了解模板的使用方法和基本原理
实验内容:
l 试设计一个类,在其中利用模板类
实验步骤:
1、实例一
本例中设计一个存储模板类,可以用其来存取不同的数据类型,可以完成元素赋值和取元素值等基本操作。
#include<iostream.h>
#include<stdlib.h>
template <class T>
class Store
{
T item;
int haveValue;
public:
Store();
T GetElement();
void PutElement(const T& x);
};
template <class T>
Store<T>::Store():haveValue(0){}
template <class T>
T Store<T>::GetElement()
{
if (haveValue==0)
{
cerr<<"No item present!"<<endl;
exit(1);
}
return item;
}
template <class T>
void Store<T>::PutElement(const T& x)
{
haveValue++;
item=x;
}
struct Student
{
int studID;
double gpa;
};
void main()
{
Student graduate={1000,3.5};
Store<int> A,B;
Store<Student> S;
Store<double> D;
A.PutElement(3);
B.PutElement(-7);
cout<<A.GetElement()<<" "<<B.GetElement()<<endl;
S.PutElement(graduate);
cout<< "The student id is "<<S.GetElement().studID<<endl;
cout<<"Retrieving object D "<<D.GetElement()<<endl;
}
2、实例二
设计一个通用数组模板类,能够完成数组的初始分配、扩充容量、重载[]和*运算符、复制及销毁数组,在实际应用时,根据不同情况利用不同的实际数据类型,本例中,用整型,并设计一个筛选一定范围内素数的应用程序。
(1)头文件
//array.h
#include<iostream.h>
#include<stdlib.h>
enum ErrorType{invalidArraySize,memoryAllocationError,indexOutOfRange};
char *errorMsg[]={"Invalid array size","Memory allocation error","Invalid index"};
template <class T>
class Array
{
T* alist;
int size;
void Error(ErrorType errorCommitted,int badIndex=0) const
{
cerr<<errorMsg[errorCommitted]<<endl;
exit(1);
};
public:
Array(int sz=50);
Array(const Array<T>& x);
~Array();
//Array<T>& operator=(const Array<T>& rhs);
T& operator[](int i);
operator T*()const;
int ListSize()const;
void Resize(int sz);
};
template<class T>
int Array<T>::ListSize()const
{
return size;
}
template <class T>
Array<T>::Array(int sz)
{
if (sz<=0) Error(invalidArraySize);
size=sz;
alist=new T[size];
if (alist==NULL) Error(memoryAllocationError);
}
template <class T>
Array<T>::~Array()
{
delete [] alist;
}
template <class T>
Array<T>::Array(const Array<T>& x)
{
int n=x.size;
size=n;
alist=new T[n];
if (alist==NULL) Error(memoryAllocationError);
T* srcptr=x.alist;
T* destptr=alist;
while(n--) *destptr++=*srcptr++;
}
template<class T>
T& Array<T>::operator[](int n)
{
if(n<0 ||n>size-1) Error(indexOutOfRange,n);
return alist[n];
}
template<class T>
Array<T>::operator T* ()const
{
return alist;
}
te
展开阅读全文