实验目的和要求
- 熟悉类的定义格式和类中成员的访问权限。
- 构造函数与析构函数的调用时机与顺序。
- 掌握对象的定义以及对象的初始化的时机与方法。
实验内容
1. 下面程序sy3_1.cpp中用ERROR标明的语句有错,在不删除和增加代码行的情况下,改正错误语句,使其正确运行。
//sy_1.cpp
#include<iostream>
using namespace std;
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 a1(1),a2(2);
a1.print();
//cout<<a2.a<<endl; //ERROR
a2.print();
return 0;
}
源程序已被注释。添加修改后程序。
运行结果
结果分析:
- a是私有数据。所以main函数不能访问并输出
a2.a
。所以改为a2.print()
。- 该程序中定义了两个对象a1和a2。类中有两个构造函数。a1用成员选择运算符“
.
”访问成员函数print()
。 创建对象a1,a2时调用有一个参数构造函数,输出第一二行结果。a1,a2用成员选择运算符“.
”访问成员函数print()
,输出第三四行结果。然后运行析构函数输出第五六行结果。
2.调试下列程序。
//sy3_2.cpp
#include<iostream>
using namespace std;
class TPoint
{
public:
TPoint(int x,int y){X=x; Y=y;}
TPoint(TPoint &p); //
~TPoint( ){cout<<"Destructor is called\n";}
int getx(){return X;}
int gety(){return Y;}
private:
int X,Y;
};
TPoint::TPoint(TPoint &p)
{
X=p.X;
Y=p.Y;
cout<<"Copy-initialization constructor is called\n";
cout<<"Constructor is called\n";
}
int main()
{
TPoint p1(4,9);
TPoint p2(p1);
TPoint p3=p2; //用对象P2创建新对象P3。
cout<<"p3=("<<p3.getx()<<","<<p3.gety()<<")\n";
return 0;
}
在该程序中,将TPoint类的带有两个参数的构造函数进行修改,在该函数体内添加下述语句:cout<<""Constrcutor is called.\n
;
1. 写出程序的输出结果,并解释输出结果。
输出结果:
结果分析:
该程序声明了三个对象p1,p2和p3。类中有三个构造函数。创建对象p1时调用有两个参数的构造函数TPoint(int x,int y){X=x; Y=y;}
。创建对象p2时调用有一个参数的构造函数,输出一二行,创建对象p3时调用有一个参数的构造函数,输出第三四行。然后执行输出语句cout<<"p3=("<<p3.getx()<<","<<p3.gety()<<")\n";
调用有一个参数的get函数,输出第五行结果。最后分别执行析构函数输出后续结果。
2.按下列要求进行调试:在主函数体内添加下列说明语句:TPoint P4,P5(2);
调试程序会出现什么现象?为什么?如何解决?(对已有的构造函数进行修改)结合运行结果分析如何使用不同的构造函数创建不同的对象。
调试结果:
这是由于类class中没有定义TPoint::TPoint()
函数,所以不能执行这个语句。
解决方法:
//sy3_2.cpp
#include<iostream>
using namespace std;
class TPoint
{
public:
TPoint(); //无参构造函数
TPoint(int a); //有一个参数的构造函数
TPoint(int x,int y){X=x; Y=y;} //有两个参数的构造函数
TPoint(TPoint &p); //拷贝构造函数
~TPoint( ){cout<<"Destructor is called\n";} //析构函数
int getx(){return X;} //有一个参数的get函数
int gety(){return Y;} //有一个参数的get函数
private:
int X,Y,A;
};
TPoint::TPoint()
{
cout<<"default constructor is clalled!\n";
};
TPoint::TPoint(TPoint &p)
{
X=p.X;
Y=p.Y;
cout<<"Copy-initialization constructor is called\n";
cout<<"Constructor is called\n";
};
TPoint::TPoint(int a)
{
A=a;
cout<<"constructor is called"<<A<<endl;
}
int main()
{
TPoint p1(4,9);
TPoint p2(p1);
TPoint p3=p2; //用对象P2初始化对象P3。
TPoint p4,p5(2);
cout<<"p3=("<<p3.getx()<<","<<p3.gety()<<")\n";
return 0;
}
输出结果:
3、对教材中Li3_11.cpp的主函数做如下修改:
(1)将Heapclass *pa1,*pa2 改为Heapclass *pa1,*pa2,*pa3;
(2)在语句pa2=new Heapclass 后增加语句pa3=new Heapclass(5);
(3)将语句 if(!pa1||!pa2) 改为if(!pa1||!pa2||!pa3)
(4)在语句delete pa2 后增加语句delete pa3;
写出程序的输出结果,并解释输出结果。
#include<iostream>
using namespace std;
class heapclass
{
public:
heapclass(int x);
heapclass();
~heapclass();
private:
int i;
};
heapclass::heapclass(int x)
{
i=x;
cout<<"constrcutor is called."<<i<<endl;
}
heapclass::heapclass()
{
cout<<"default constructor is called."<<endl;
}
heapclass::~heapclass()
{
cout<<"destructor is called."<<endl;
}
int main()
{
heapclass * pa1,* pa2,*pa3;
pa1= new heapclass(4); //分配空间
pa2= new heapclass; //分配空间
pa3= new heapclass(5); //分配空间
if(!pa1||!pa2||!pa3) //检查空间
{
cout<<"out of memory!"<<endl;
return 0;
}
cout<<"exit main"<<endl;
delete pa1;
delete pa2;
delete pa3;
return 0;
}
输出结果:
程序分析:
pa1,pa2,pa3中是三个指向类heapclass的对象指针,使用运算符new给他们赋值,同时对他们指向的对象进行初始化。 pa1= new heapclass(4); pa2= new heapclass; pa3= new heapclass(5);
执行这三句分别调用了有参无参有参三次函数,输出结果前三句。
检查空间有足够的内存所以跳过if语句中的输出,而后输出exit main。最后使用运算符delete系统自动调用析构函数,输出最后三句。又使用运算符delete释放了这三个指针所指向的对象。
#include<iostream>
using namespace std;
class rectangle
{
public:
rectangle(){len=0;wid=0;} //wucan
rectangle(double l,double w){len=l;wid=w;}
double zc(){return 2*(len+wid);}
double mj(){return len*wid;}
double getl(){return len;}
double getw(){return wid;}
void print(double a,double b){len= a; wid=b;}
printf()
{
cout<<"length:"<<len<<endl;
cout<<"width:"<<wid<<endl;
}
private:
int len, wid;
};
int main()
{
rectangle p1;
rectangle p2(8.0,10.0);
cout<<"p1的矩形尺寸:"<<endl;
p1.printf();
cout<<"p2的矩形尺寸:"<<endl;
p2.printf();
cout<<"p2的周长为:"<<p2.zc()<<endl;
cout<<"p2的面积为:"<<p2.mj()<<endl;
cout<<"p2的长度为:"<<p2.getl()<<endl;
cout<<"p2的宽度为:"<<p2.getw()<<endl;
p2.print(3.0,4.0);
cout<<"修改后的矩形的尺寸:"<<endl;
p2.printf();
return 0;
}
输出结果:
分析与讨论
1、类中私有成员的访问权限;
- 只有类中的函数才能访问类中私有成员。
2、构造函数和析构函数的调用顺序;
- 在对象创建时,先用构造函数对其进行初始化,在程序结束后用析构函数释放由构造函数分配的内存,而且析构函数的执行顺序与构造函数的执行顺序刚好相反。
3、何时进行对象初始化?如何进行?(提示:注意分一般对象与堆对象讨论)
- 一般对象:在对象的创建时对其进行初始化,可以用构造函数或者用拷贝构造函数进行初始化。
- 堆对象:用new进行分配空间,再调用构造函数进行初始化。
来源:CSDN
作者:AIIN
链接:https://blog.csdn.net/SherAIIN/article/details/80072140