实验三 构造函数和析构函数
班级: 学号: 姓名: 成绩:
一. 实验目的
1.理解构造函数和析构函数作用;
2.掌握各种类型的构造函数和析构函数的使用;
3.掌握构造函数和析构函数的调用顺序。
二. 使用的设备和仪器
计算机+Windows XP +Visual C++6.0
三. 实验内容及要求
1.阅读程序,写出运行结果,然后上机运行,将机器运行结果与人工运行的结果进行比较,并对每一行输出做出分析。
(1)
#include <iostream>
using namespace std;
class MyClass
{
public:
MyClass();
MyClass(int xx);
MyClass(int xx,int yy);
MyClass(MyClass &);
void Display();
void Set(int, int);
~ MyClass();
private:
int x,y;
};
MyClass:: MyClass()
{
cout<<"执行无参构造函数:" ;
x=0;y=0;
cout<<"x="<<x<<"y="<<y<<endl;
}
MyClass:: MyClass(int xx)
{
cout<<"执行一个参数构造函数:" ;
x=xx;y=0;
cout<<"x="<<x<<"y="<<y<<endl;
}
MyClass:: MyClass(int xx,int yy)
{
cout<<"执行两个参数构造函数:" ;
x=xx;y=yy;
cout<<"x="<<x<<"y="<<y<<endl;
}
MyClass:: MyClass(MyClass &a)
{
cout<<"执行复制构造函数:" ;
x=a.x;y=a.y;
cout<<"x="<<x<<"y="<<y<<endl;
}
void MyClass:: Display()
{
cout<<"执行显示函数:" ;
cout<<"x="<<x<<"y="<<y<<endl;
}
void MyClass:: Set(int xx=0,int yy=0)
{
cout<<"执行设置函数:" ;
x=xx;y=yy;
cout<<"x="<<x<<"y="<<y<<endl;
}
MyClass:: ~MyClass ()
{
cout<<"执行析构函数:" ;
cout<<"x="<<x<<"y="<<y<<endl;
}
void main() //int main
{
MyClass a(12,34);
a.Set(20);
a.Display();
MyClass b(a);
b.Display();
MyClass c;
MyClass d(222);
{
MyClass e(788,453);
d.Display();
}
c.Display();
}
运行结果:
人工预测:
执行两个参数函数构造x=12y=34
执行设置函数:x=20y=0
执行显示函数:x=20y=0
执行无参数函数构造:x=0y=0
执行一个参数函数造:x=222y=0
执行两个参数函数构造:x=788y=453
执行显示函数:x=222y=0
//执行析构函数x=788y=453
执行显示函数:x=0y=0
执行析构函数:x=788y=453
执行析构函数:x=222y=0
执行析构函数:x=0y=0
执行析构函数:x=12y=34
运行结果
(2)
#include<iostream>
using namespace std;
class A
{
public:
A(int x=100,double y=1.2){a=x;b=y;}
void show(char *pt) //void show(string pt)
{ cout<<pt<<":"<<endl;
cout<<"a="<<a<<endl;
cout<<"b="<<b<<endl;
}
private:
int a;
double b;
};
void main() // int main()
{
A obj1,obj2(100,3.5);
obj1.show("obj1");
obj2.show("obj2");
A *p;
p=&obj1;
p->show("p->obj1");
(*p).show("(*p)obj1");
p=&obj2;
p->show("p->obj2");
(*p).show("(*p)obj2");
p=new A;
p->show("p->new");
delete p;
}
运行结果:
人工运行:
obj1:
a=100
b=1.2
Obj2:
a=100
b=3.5
p->obj1:
a=100
b=1.2
(*p)obj1:
a=100
b=1.2
p->obj2:
a=100
b=3.5
(*p)obj2
a=100
b=3.5
P->new:
a=100
b=3.5
上机运行:
自己写完运行结果后,到环境中运行时发现程序有一点问题,就做了一点修改(上方程序中后面有注释部分就是自己进行的修改)。
(3)
#include <iostream>
using namespace std;
class Complex
{
public:
Complex();
Complex (double x, double y);
Complex (Complex & c);
~ Complex ();
double GetRel() { return rel;}
double GetImg() { return img;}
private:
double rel, img;
};
Complex::Complex()
{
rel=0; img=0;
cout<<"缺省构造函数被调用: ";
cout<<"("<<rel<<","<<img<<")"<<endl;
}
Complex::Complex(double x, double y)
{
rel=x; img=y;
cout<<"构造函数被调用: ("<<rel<<","<<img<<")"<<endl;
}
Complex::Complex(Complex & c)
{
rel = c.rel;
img = c.img;
cout<<"复制构造函数被调用: ";
cout<<"("<<rel<<","<<img<<")"<<endl;
}
Complex::~ Complex ()
{
cout<<"析构函数被调用: ("<<rel<<","<<img<<")"<<endl;
}
//函数定义
Complex fun(Complex c)
{
cout<<"在函数 fun()中."<<endl;
double x, y;
x=c.GetRel()*10;
y=c.GetImg()+100;
Complex temp(x, y);
return temp;
}
void main() //int
{
Complex c1(6.8, 98.23),c2;
c2=fun(c1);
cout<<"c2=("<<c2.GetRel()<<",";
cout<<c2.GetImg()<<")"<<endl;
}
运行结果:
人工运行:
构造函数被调用:6.8,98.23
缺省函数被调用:0,0
在函数fun()中.
构造函数被调用:68,198.23
析构函数被调用:68,198.23
c2=68,198.23
析构函数被调用:68,198.23
析构函数被调用:0,0
析构函数被调用:6.8,98.23
上机运行:
运行比较:对数值的输出没有加();
没有考虑到复值函数的调用;
在函数fun()中后面涉及到两次析构函数的调用,而在c2=(68,198.23)后面只有两次析构,对系统何时调用析构还是不懂;
比较郁闷的是为什么没有缺省函数的析构???
2.编写一个Number类,它有两个整型数据成员x和y。成员函数包括构造、输入、输出数、设置以及对两个数据进行加、减、乘、除运算。在主函数中,定义不同的Number类对象,并测试以上功能。
程序代码:
#include<iostream>
3.using namespace std;
4.class Number
5.{
6. private:
7. int x,y;
8. public:
9. void Input();
10. void Set(int a=0,int b=0);
11. void Dispos();
12. void Show();
13.};
14.void Number::Set(int a,int b)
15.{
16. x=a;
17. y=b;
18.}
19.
20.void Number::Show()
21.{
22. cout<<"x="<<x<<" "<<"y="<<y<<endl;
23.}
24.void Number::Input()
25.{
26. cin>>x;
27. cin>>y;
28.
29.}
30.void Number::Dispos()
31.{
32. cout<<"x*y="<<x*y<<endl;
33. cout<<"x/y="<<x/y<<endl;
34. cout<<"x+y="<<x+y<<endl;
35. cout<<"x-y="<<x-y<<endl;
36.}
37.int main()
38.{
39. Number a;
40. cout<<"plase input x and y:"<<endl;
41. a.Input();
42. a.Show();
43. a.Dispos();
44. a.Set(5,2);
45. cout<<endl;
46. a.Dispos();
47.
48.return 0;
49.}
3.在实验二第2题中增加构造函数和析构函数,在main函数中定义一个存放N个学生信息的对象数组,并定义以下函数完成相应的动能。
Input(Student stu[],int n)——输入N个学生的信息;
Show(Student stu[],int n) ——输出N个学生的信息;
Max(Student stu[],int n)——输出N个学生中成绩最高的学生信息。
代码:
#include<iostream>
#include<string>
#include<iomanip>
const int N=100;
using namespace std;
class Student
{
private:
int num;
string name;
double english,math,c;
public:
void Input();
void Show();
int Are();
void Set(int x=0,string y="",double z=0,double h=0,double k=0);
~Student(){};
};
void Student::Input()
{
cout<<"学号:";
cin>>num;
cout<<"名字:";
cin>>name;
cout<<"请输入数学,英语,c++成绩:"<<endl;
cin>>math>>english>>c;
}
void Student::Show()
{
cout<<setw(6)<<num<<setw(10)<<name<<setw(6)<<math<<setw(6)<<english<<setw(6)<<c<<endl;
/* cout<<"学号:"<<num<<endl;
cout<<"名字:"<<name<<endl;
cout<<"数学:"<<math<<endl;
cout<<"英语:"<<english<<endl;
cout<<"c++:"<<c<<endl;*/
}
int Student::Are()
{
return (math+english+c)/3;
}
void Student::Set(int x,string y,double z,double h,double k)
{
num=x;
name=y;
english=z;
math=h;
c=k;
}
int Max(Student*a,int n)
{
int m;
for(int i=0;i<n-1;i++)
{
if((a[i].Are()<a[i+1].Are()))
{
m=i+1;
}
}
return m;
}
int main()
{
int n,k;
int i;
Student*stu=new Student[N];
cout<<"请输入学生数:";
cin>>n;
for(i=0;i<n;i++)
{
stu[i].Input();
}
cout<<setw(6)<<"学号" <<setw(10)<<"姓名"<<setw(6)<<"数学"<<setw(6)<<"英语"<<setw(6)<<"c"<<endl;
for(i=0;i<n;i++)
{
stu[i].Show();
}
k=Max(stu,n);
cout<<"成绩最好的信息:"<<endl;
cout<<setw(6)<<"学号" <<setw(10)<<"姓名"<<setw(6)<<"数学"<<setw(6)<<"英语"<<setw(6)<<"c"<<endl;
stu[k].Show();
delete[]stu;
return 0;
}
选做题:
4.某单位对员工收入进行管理,创建一个Income类,包含的数据成员编号num、姓名name、工资wage;成员函数包括:
构造函数
Input() 输入
Show() 输出(输出编号、姓名、工资、应缴税额以及实际收入)
SetWage( double m ) 设置工资值
GetTaxrate( ) 计算应缴税额
GetIncome( ) 计算职工的实际收入
在主函数中,定义不同的Income类对象,并测试以上功能。
(其中,计算应缴税额的方式如下。假设该城市个人所得税的税基为2000元,而其征收个人所得税的规定如下:不超过税基免征税,按超过税基部分征收所得税。超过部分在2000以下,征税5%;5000元以下,征税10%;10000元以下,征税15%;10000元以上,征税20%。)
代码:
#include<iostream>
#include<string>
#include<iomanip>
using namespace std;
class Income
{
private:
int num;
string name;
float wage;
public:
void Input();
void Show(Income &);
void Set(double m){wage=m;}
double GetTaxrate(Income&);
double GetIncome(Income&);
};
void Income::Input()
{
cout<<"编号:";
cin >>num;
cout<<"姓名:";
cin>>name;
cout<<"工资:";
cin>>wage;
}
void Income::Show(Income &s)
{
cout<<setw(10)<<"编号"<<setw(10)<<"姓名"<<setw(15)<<"工资"<<setw(18)<<"应交税费"<<setw(18)<<"实际收入"<<endl;
cout<<setw(10)<<s.num<<setw(10)<<s.name<<setw(15)<<s.wage<<setw(18)<<s.GetTaxrate(s)<<setw(18)<<s.GetIncome(s)<<endl;
}
double Income::GetTaxrate(Income&s)
{
double a;
if(s.wage-2000<1)
{
a=0;
}
else if(s.wage-2000<2001)
{
a=(s.wage-2000)*0.05;
}
else if(s.wage-2000<5001)
{
a=2000*0.05+(s.wage-4000)*0.1;
}
else if(s.wage-2000<10000)
{
a=2000*0.05+3000*0.1+(s.wage-7000)*0.15;
}
else if(s.wage-2000>10000)
{
a=2000*0.05+3000*0.1+5000*0.15+(s.wage-12000)*0.2;
}
return a;
}
double Income::GetIncome(Income &s)
{
double b,a;
a=s.GetTaxrate(s);
b=wage-a;
return b;
}
int main()
{
Income s;
s.Input();
cout<<"员工信息为:"<<endl;
s.Show(s);
cout<<"设置后信息为:"<<endl;
s.Set(7000);
s.Show(s);
return 0;
}
5.在第3题的基础上,还可以增加以下函数对N个学生平均成绩进行排序的函数
Sort(Student stu[],int n)。(上交答案时,该题只交这个函数的代码以及运行结果界面即可。)
#include<iostream>
#include<string>
#include<iomanip>
const int N=100;
using namespace std;
class Student
{
private:
int num;
string name;
double english,math,c;
public:
void Input();
void Show();
int Are();
void Set(int x=0,string y="",double z=0,double h=0,double k=0);
~Student(){};
};
void Student::Input()
{
cout<<"学号:";
cin>>num;
cout<<"名字:";
cin>>name;
cout<<"请输入数学,英语,c++成绩:"<<endl;
cin>>math>>english>>c;
}
void Student::Show()
{
cout<<setw(6)<<num<<setw(10)<<name<<setw(6)<<math<<setw(6)<<english<<setw(6)<<c<<endl;
}
int Student::Are()
{
return (math+english+c)/3;
}
void Student::Set(int x,string y,double z,double h,double k)
{
num=x;
name=y;
english=z;
math=h;
c=k;
}
int Max(Student*a,int n)
{
int m;
for(int i=0;i<n-1;i++)
{
if((a[i].Are()<a[i+1].Are()))
{
m=i+1;
}
}
return m;
}
void Sort(Student*a,int n)
{
float t;
float b[N];
for(int i=0;i<n;i++)
{
b[i]=a[i].Are();
}
for(int i=0;i<n-1;i++)
{
for(int j=i+1;j<n;j++)
{
if(b[i]<b[j])
t=b[i];
b[i]=b[j];
b[j]=t;
}
}
cout<<"排序为:"<<endl;
for(int i=0;i<n;i++)
{
cout<<b[i]<<endl;
}
}
int main()
{
int n,k;
int i;
Student*stu=new Student[N];
cout<<"请输入学生数:";
cin>>n;
for(i=0;i<n;i++)
{
stu[i].Input();
}
cout<<setw(6)<<"学号" <<setw(10)<<"姓名"<<setw(6)<<"数学"<<setw(6)<<"英语"<<setw(6)<<"c"<<endl;
for(i=0;i<n;i++)
{
stu[i].Show();
}
k=Max(stu,n);
cout<<"成绩最好的信息:"<<endl;
cout<<setw(6)<<"学号" <<setw(10)<<"姓名"<<setw(6)<<"数学"<<setw(6)<<"英语"<<setw(6)<<"c"<<endl;
stu[k].Show();
Sort(stu,n);
delete[]stu;
return 0;
}
四. 实验步骤
1、程序代码:
运行结果:
2、程序代码:
运行结果:
五. 实验总结
1.实验中遇到的问题及解决方法
1)调用成员函数时直接Show();没有加对象名;
通过翻阅其他程序发现不同之处。
2)误以为只要首地址加函数就可以对多个对象进行处理:例如定义Student stu=new[100];对对象进行处理直接stu.Show();
这个问题实在不应该有,经过认真思考就能发现问题。计算机那么笨怎么可能识别stu 就算识别没有条件 它又怎么知道何时停止;
3)对setw()运用,总是不能使之完全对应,
4)偶尔对私有数据进行访问,但一般都能及时发现,
5)第一题第三个小题:
在函数fun()中后面涉及到两次析构函数的调用,而在c2=(68,198.23)后面只有两次析构,对系统何时调用析构还是不懂;
比较郁闷的是为什么没有缺省函数的析构???
2.个人收获和体会
学习c++后,深深体会到它的方便,很多小细节省去了比如输出输入加d%flf%或者是是否用&号,新的东西总会产生新的问题,例如类中涉及到构造和析构,还是不懂何时系统会自动调用它们。
通过这些练习,还是发现自己练习太少,写起程序来还不能做到得心应手,还是会犯一些低级错误,例如少了头文件,分号;return0等
这样自己在课下提前做,虽然没有时间限制,不过也逐渐是自己有了那种编程思想,写起来也逐渐顺手起来了。