实验二 类与对象
实验目的和要求
1.掌握类、类的数据成员、类的成员函数的定义方式。
2.理解类成员的访问控制方式。
3.掌握对象的定义和操作对象的方法。
4.理解构造函数和析构函数的定义与执行过程。
5.掌握重载构造函数的方法。
6.了解拷贝构造函数的定义方法。
实验内容
1.下面程序中有错,在不删除和增加代码行的情况下,改正错误语句,使其正确运行。
#include<iostream.h>
class Aa
{
public:
Aa(int i=0)
{
a=i;
cout<<"Constructor "<<a<<endl;
}
~Aa()
{
cout<<"Destructor "<<a<<endl;
}
void print()
{
cout<<a<<endl;
}
private:
int a;
};
int main()
{
Aa al(1),a2(2);
al.print();
cout<<a2.a<<endl;
return 0;
}
2.检查下面的程序,找出其中的错误,并改正。然后上机调试,使程序能正常运行。
(1)
#include<iostream.h>
class Date
{
void set_date();
void show_date();
int year;
int month;
int day;
};
Date d;
int main()
{
set_date();
show_date();
}
void set_date()
{
cin>>d.year;
cin>>d.month;
cin>>d.day;
}
void show_date()
{
cout<<d.year<<'/'<<d.month<<'/'<<d.day<<endl;
}
(2)
#include<iostream.h>
class A
{
public:
void A(int i=0)
{
m=i;
}
void show()
{
cout<<m<<endl;
}
void ~A(){}
private:
int m;
};
int main()
{
A a(5);
a.m+=10;
a.show();
return 0;
}
(3)
#include<iostream.h>
class X
{
private:
int a=0;
int &b;
void setA(int i)
{
a=i;
}
X(int i)
{
a=i;
}
public:
int X()
{
a=b=0;
}
X(int i,int j)
{
a=i;
b=j;
}
void setC(int k)
{
c=c+k;
}
};
void main()
{
X x1;
X x2(2);
X x3(1,2);
x1.setA(3);
}
3.调试下列程序。
#include<iostream.h>
class TPoint
{
private:
int X,Y;
public:
TPoint(int x,int y)
{
X=x;
Y=y;
cout<<"Constructor is called"<<endl;
}
TPoint(TPoint &p);
~TPoint()
{ cout<<"Destructor is called"<<endl; }
int getx()
{ return X; }
int gety()
{ return Y; }
};
TPoint::TPoint(TPoint &p)
{
X=p.X;
Y=p.Y;
cout<<"Copy-initialization Constructor is called"<<endl;
}
void main()
{
TPoint p1(4,9);
TPoint p2(p1);
TPoint p3 = p2;
cout<<"p3=("<<p3.getx()<<","<<p3.gety()<<")"<<endl;
}
(1)写出程序的输出结果,并解释输出结果。
(2)按下列要求进行调试:
在主函数体内,添加下列说明语句:
TPoint p4,p5(2);
调试程序会出现什么现象?为什么?如何解决?(提示:对已有的构造函数进行适当修改)结合运行结果分析如何使用不同的构造函数创建不同的对象。
(3)在主函数内使用new创建不同参数动态两个动态对象,输出其坐标,并用delete删除之。运行程序,分析运行结果。
(4)在程序中定义个全局对象,在主函数最前添加语句:
cout<<"Enter main"<<endl;
运行程序,分析运行结果。
4.完善程序,并写出运行结果
根据程序要求,完善程序后输入源程序,编译连接,并写出运行结果。
如果某个自然数除了1和它本身外还有其他因子,则这个自然数就是合数(非素数)。试定义一个类NUM,从3开始向上试探找出n个连续的自然数,且它们都是合数。当找到第一组连续的n个合数后,即停止查找。
具体要求如下:
(1)私有成员
int n : 存放满足条件的连续自然数的个数。
int *p: 根据n的值申请一个动态数组用来存放求出的满足条件的n个自然数。
(2)公有成员函数
NUM(int n1): 构造函数,用n1初始化n,根据n的值申请动态数组空间,使p指向该动态数组空间。
int yes(int x): 判断x是否为合数。如果是,返回1,否则返回0。
void fun(): 从3开始向上试探找出n个连续的自然数,且它们都是合数,并依次存入动态数组。
void print(): 输出满足条件的n个合数。
~NUM(): 析构函数,释放动态数组所占用的存储空间。
(3)在主函数中定义一个NUM类的对象num,求出10个连续的合数。然后通过对象num调用成员函数求出10个连续的合数,并输出计算结果。
#include <iostream.h>
class NUM
{ //定义数据类NUM
private:
int n;
int *p;
public:
NUM(int n1)
{
n=n1;
p= ; //动态分配存放连续合数的存储空间
}
int yes(int x)
{
for(int i=2;i<=x/2;i++)
if (x%i==0)
return 1;
return 0;
}
void fun(void)
{
int j;
for(int i=3;1;i++)
{
j=0;
while( &&j<n)
{
p[j]=i;
j++;
i++;
}
if(j==n)
break;
}
}
void print(void)
{
cout<<"找到的"<<n<<"个连续合数为:"<<endl;
for(int i=0;i<n;i++)
cout<<p[i]<<" ";
cout<<endl;
}
~NUM()
{
; //释放在构造函数中申请的存储空间
}
};
void main()
{
cout<<"请输入要求的连续合数的个数(例如10):";
int n;
cin>>n;
NUM num(n);
; //寻找连续的合数,并存入动态申请的存储空间中
; //输出寻找到的合数
}
5.请定义一个矩形类(Rectangle),私有数据成员为矩形的长度( len)和宽度(wid),缺省构造函数置len和wid为0,有参构造函数置len和wid为对应形参的值,另外还包括求矩形周长、求矩形面积、取矩形长度和宽度、修改矩形长度和宽度为对应形参的值、输出矩形尺寸等公有成员函数。要求输出矩形尺寸的格式为“length:长度,width:宽度”。编写主函数对定义的类进行测试。
6.声明一个时间类,时间类中有3个私有数据成员(Hour,Minute,Second)和两个公有成员函数(SetTime和PrintTime)。SetTime根据传递的3个参数为对象设置时间;PrintTime负责将对象表示的时间显示输出,输出格式为“Hour:Minute:Second”。
(1)在主函数中,建立一个时间类的对象,设置时间为9点20分30秒并显示该时间。
(2)使用构造函数代替上面的SetTime成员函数,并在主函数中使用构造函数设置时间为10点40分50秒,并显示该时间。
(3)重载时间类的构造函数(不带参数)使小时、分、秒均为0。
(4)在时间类的析构函数中输出"Good bye!”
(5)定义拷贝构造函数并调用。
7.下面是一个整型链表类intList的声明,请给出该类所有数据成员的类外定义,并在主函数中测试该类。
class intList
{
protected:
struct Node
{
int data;
Node *next;
};
Node *L;
public:
intList(); //构造函数
~intList(); //析构函数
bool Insert(int i,int elem);
bool Remove(int i,int &elem);
//删除链表的第i个位置的元素,删除成功返回true,失败返回false
int Find(int elem);
//在链表中查找值为elem的元素,找到返回该元素在链表中的位置,否则返回0
int Length(); //返回链表长度(元素个数)
void PrintList(); //输出链表
};
参考答案(非权威,仅仅是我自己的理解,如有错误,欢迎批评指正!)
第一题:
#include<iostream.h>
class Aa
{
public:
Aa(int i=0)
{
a=i;
cout<<"Constructor "<<a<<endl;
}
~Aa()
{
cout<<"Destructor "<<a<<endl;
}
void print()
{
cout<<a<<endl;
}
private:
int a;
};
int main()
{
Aa al(1),a2(2);
al.print();
a2.print();
return 0;
}
第二题
(1)
#include<iostream.h>
class Date
{
public:
void set_date();
void show_date();
private:
int year;
int month;
int day;
};
Date d;
int main()
{
d.set_date();
d.show_date();
return 0;
}
void Date::set_date()
{
cin>>year;
cin>>month;
cin>>day;
}
void Date::show_date()
{
cout<<year<<'/'<<month<<'/'<<day<<endl;
}
(2)
#include<iostream.h>
class A
{
public:
A(int i=0)
{
m=i;
}
void show()
{
cout<<m<<endl;
}
~A(){}
friend void add(A &);
private:
int m;
};
void add(A &a)
{
a.m+=10;
}
int main()
{
A a(5);
add(a);
a.show();
return 0;
}
(3)
#include<iostream.h>
class X
{
private:
int a,b,c;
public:
X(int i)
{
a=i;
}
X()
{
a=b=0;
}
X(int i,int j)
{
a=i;
b=j;
}
void setC(int k)
{
c=c+k;
}
void setA(int i)
{
a=i;
}
};
void main()
{
X x1;
X x2(2);
X x3(1,2);
x1.setA(3);
}
第三题
(1)
void main()
{
TPoint p1(4,9); //调用构造函数初始化p1
TPoint p2(p1); //显示调用拷贝构造函数初始化p2
TPoint p3 = p2; //对象之间的赋值,由于之前没有定义p3,因此用另一个同类的对象给其赋值时,会调用拷贝构造函数。
cout<<"p3=("<<p3.getx()<<","<<p3.gety()<<")"<<endl; //输出p3在赋值后的x和y
}
(2)
答:调试程序会程序错误,原因是对于无输入的对象和只要一个输入值的对象没有相应的构造函数,要解决也挺简单,就是在说明部分加上相应的构造函数就可以了。
修改后的程序如下:
#include<iostream.h>
class TPoint
{
private:
int X,Y;
public:
TPoint()
{
X=Y=0;
cout<<"A Constructor is called"<<endl;
}
TPoint(int i)
{
X=i;
Y=0;
cout<<"B Constructor is called"<<endl;
}
TPoint(int x,int y)
{
X=x;
Y=y;
cout<<"Constructor is called"<<endl;
}
TPoint(TPoint &p);
~TPoint()
{ cout<<"Destructor is called"<<endl; }
int getx()
{ return X; }
int gety()
{ return Y; }
};
TPoint::TPoint(TPoint &p)
{
X=p.X;
Y=p.Y;
cout<<"Copy-initialization Constructor is called"<<endl;
}
void main()
{
TPoint p1(4,9);
cout<<"p1=("<<p1.getx()<<","<<p1.gety()<<")"<<endl;
TPoint p2(p1);
cout<<"p2=("<<p2.getx()<<","<<p2.gety()<<")"<<endl;
TPoint p3 = p2;
cout<<"p3=("<<p3.getx()<<","<<p3.gety()<<")"<<endl;
TPoint p4,p5(2);
cout<<"p4=("<<p4.getx()<<","<<p4.gety()<<")"<<endl;
cout<<"p5=("<<p5.getx()<<","<<p5.gety()<<")"<<endl;
}
(3)
#include<iostream.h>
class TPoint
{
private:
int X,Y;
public:
TPoint(int x,int y)
{
X=x;
Y=y;
cout<<"Constructor is called"<<endl;
}
TPoint(TPoint &p);
~TPoint()
{
cout<<"Destructor is called"<<endl;
}
int getx()
{ return X; }
int gety()
{ return Y; }
};
TPoint::TPoint(TPoint &p)
{
X=p.X;
Y=p.Y;
cout<<"Copy-initialization Constructor is called"<<endl;
}
void main()
{
TPoint *p1=new TPoint(4,9);
cout<<"p1=("<<p1->getx()<<","<<p1->gety()<<")"<<endl;
delete p1;
}
(4)
#include<iostream.h>
class TPoint
{
private:
int X,Y;
public:
TPoint(int x,int y)
{
X=x;
Y=y;
cout<<"Constructor is called"<<endl;
}
TPoint(TPoint &p);
~TPoint()
{
cout<<"Destructor is called"<<endl;
}
int getx() { return X; }
int gety() { return Y; }
void ShowPoint()
{
cout<<"p1=("<<X<<","<<Y<<")"<<endl;
}
};
TPoint::TPoint(TPoint &p)
{
X=p.X;
Y=p.Y;
cout<<"Copy-initialization Constructor is called"<<endl;
}
void main()
{
cout<<"Enter main"<<endl;
TPoint *p1=new TPoint(4,9);
p1->ShowPoint();
delete p1;
}
第四题:
#include <iostream.h>
class NUM
{ //定义数据类NUM
private:
int n;
int *p;
public:
NUM(int n1)
{
n=n1;
p=new int[n]; //动态分配存放连续合数的存储空间
}
int yes(int x)
{
for(int i=2;i<=x/2;i++)
if (x%i==0) return 1;
return 0;
}
void fun(void)
{
int j;
for(int i=3;1;i++)
{
j=0;
while(yes(i)&&j<n)
{
p[j]=i;
j++;
i++;
}
if(j==n) break;
}
}
void print(void)
{
cout<<"找到的"<<n<<"个连续合数为:"<<endl;
for(int i=0;i<n;i++)
cout<<p[i]<<" ";
cout<<endl;
}
~NUM()
{
if(p) delete[]p; //释放在构造函数中申请的存储空间
}
};
void main()
{
cout<<"请输入要求的连续合数的个数(例如10):";
int n;
cin>>n;
NUM num(n);
num.fun(); //寻找连续的合数,并存入动态申请的存储空间中
num.print() ; //输出寻找到的合数
}
第五题:
#include<iostream.h>
class Rectangle
{
private:
int len,wid;
public:
Rectangle()
{
len=wid=0;
cout<<"First Constructor is called"<<endl;
}
Rectangle(int i,int w)
{
len=i;
wid=w;
cout<<"Second Constructor is called"<<endl;
}
void Set_Rectangle()
{
cin>>len;
cin>>wid;
}
int Get_Perimeter() { return 2*(len+wid); }
int Get_Area() { return len*wid; }
int get_len() { return len; }
int get_wid() { return wid; }
~Rectangle() { cout<<"Destructor is called"<<endl; }
};
void main()
{
int temp;
Rectangle rect,Default(8,9);
cout<<endl;
cout<<"默认长度:"<<Default.get_len()<<" , "<<"默认宽度:"<<Default.get_wid()<<endl;
cout<<"矩形的周长为:"<<Default.Get_Perimeter()<<endl;
cout<<"矩形的面积为:"<<Default.Get_Area()<<endl;
cout<<endl;
cout<<"是否需要修改参数 (1:修改 0:退出): ";
cin>>temp;
while(temp==1)
{
cout<<"请输入矩形的长和宽:"<<endl;
rect.Set_Rectangle();
cout<<"长度:"<<rect.get_len()<<" , "<<"宽度:"<<rect.get_wid()<<endl;
cout<<"矩形的周长为:"<<rect.Get_Perimeter()<<endl;
cout<<"矩形的面积为:"<<rect.Get_Area()<<endl;
cout<<endl;
cout<<"是否需要修改参数 (1:修改 0:退出): ";
cin>>temp;
}
cout<<endl;
}
第六题:
#include<iostream.h>
class Time
{
private:
int Hour,Minute,Second;
public:
Time()
{
Hour=Minute=Second=0;
cout<<"First Constructor is called"<<endl;
}
Time(int x,int y,int z)
{
Hour=x;
Minute=y;
Second=z;
cout<<"Second Constructor is called"<<endl;
}
Time(Time &p)
{
Hour=p.Hour;
Minute=p.Minute;
Second=p.Second;
cout<<"Copy Constructor is called"<<endl;
}
void SetTime()
{
cin>>Hour;
cin>>Minute;
cin>>Second;
}
void PrintTime()
{
cout<<"时:"<<Hour<<" "<<"分:"<<Minute<<" "<<"秒:"<<Second<<endl;
}
~Time() { cout<<"Good bye!"<<endl; }
};
void main()
{
Time time;
Time T(10,40,50);
Time copy=T;
cout<<endl<<"构造函数时间为:";
T.PrintTime();
cout<<endl<<"拷贝构造函数时间为: ";
copy.PrintTime();
cout<<endl;
cout<<endl<<"请输入一个时间(时/分/秒): "<<endl<<endl;
time.SetTime();
cout<<endl<<"你所输入的时间为: ";
time.PrintTime();
cout<<endl;
}
第七题:
#include <iostream>
using namespace std;
class intList
{
protected:
struct Node
{
int data;
Node * next;
};
Node * L;
public:
intList();//构造函数
~intList(); //析构函数
bool Insert(int i, int elem) ; //向链表的第i个位置插入元素elem,插入成功返回true,失败返回false
bool Remove(int i, int &elem) ;//删除链表的第i个位置的元素elem,删除成功返回true,失败返回false
int Find(int elem); //查找值为elem的元素,返回该元素在链表的位置
int Length() ;//返回链表长度
void PrintList();//输出链表
};
intList::intList() //构造函数
{
L=new Node;
L->next=NULL;
cout<<"Constructor is called"<<endl<<endl;
}
intList::~intList() //析构函数
{
Node *p,*q;
p=L;
while ( p->next != NULL )
{
q=p->next;
delete p;
p=q;
}
delete p;
L=NULL;
cout<<endl<<"Good bye!"<<endl;
}
bool intList::Insert(int i,int elem) //向链表的第i个位置插入元素elem,插入成功返回true,失败返回false
{
Node *p,*s;
int j;
p= L;
j=0;
while ( (p!=NULL ) && (j<i-1) )
{
p=p->next;
j++;
}
if ( (p!=NULL )&& (j==i-1) )
{
s=new Node;
s->data=elem;
s->next=p->next;
p->next=s;
return true;
}
else
return false;
}
bool intList::Remove(int i,int &elem) //删除链表的第i个位置的元素elem,删除成功返回true,失败返回false
{
Node *p,*q;
int j;
p= L;
j=0;
while ( (p->next!=NULL ) && (j<i-1) )
{
p=p->next;
j++;
}
if ( (p->next!=NULL )&&(j==i-1) )
{
q=p->next;
p->next=q->next;
elem=q->data;
delete q;
return true;
}
else
return false;
}
int intList::Find(int elem) //查找值为elem的元素,返回该元素在链表的位置
{
Node *p;
int j,data;
p=L->next;
j=1;
while (p!=NULL )
{
data=p->data;
if (data==elem) break;
p=p->next;
j++;
}
if (p!=NULL ) return j;
else return 0;
}
int intList::Length() //返回链表长度
{
Node *p;
int j;
p= L->next;
j=0;
while (p!=NULL )
{
p=p->next;
j++;
}
return j;
}
void intList::PrintList() //输出链表
{
Node *p;
p=L->next;
while (p!=NULL )
{
cout<<p->data<<" ";
p=p->next;
}
cout<<endl;
}
int main()
{
intList list;
cout<<endl<<"向链表写入数据成功!"<<endl;
for(int i=1;i<10;i++) list.Insert(i,i);
list.PrintList();
cout<<"链表长度为:"<<list.Length()<<endl<<endl;
int zxl,delete_data=4;
if( list.Remove(delete_data,zxl)) cout<<endl<<"数据 "<<delete_data<<"删除成功!"<<endl;
else cout<<"删除数据失败l!"<<endl;
list.PrintList();
int find_data=6;
int num=list.Find(find_data);
if(num!=0) cout<<"找到数据 "<<find_data<<"在链表的第"<<num<<"个位置。"<<endl;
else cout<<"没有找到!"<<endl;
return 0;
}