实验3 构造函数与析构函数

实验目的和要求

  1、熟悉类的定义格式和类中成员的访问权限。

  2、构造函数与析构函数的调用时机与顺序。

  3、掌握对象的定义以及对象的初始化的时机与方法。

实验内容

  1、下面程序sy3_1.cpp中用ERROR标明的语句有错吧,在不删除和增加代码行的情况下,改正错误语句,使其正确运行。

运行程序如下:

  1. #include<iostream>
  2. using namespace std;
  3. class Aa
  4. {
  5. public:
  6. Aa( int i= 0){a=i; cout<< "Constructor"<<a<< endl;}
  7. ~Aa(){ cout<< "Destructor"<<a<< endl;}
  8. void print(){ cout<<a<< endl;}
  9. private:
  10. int a;
  11. };
  12. int main()
  13. {
  14. Aa a1(1),a2(2);
  15. a1.print();
  16. cout<<a2.a<< endl; //ERROR
  17. return 0;
  18. }
错误如下:
修改程序如下:
  1. #include<iostream>
  2. using namespace std;
  3. class Aa
  4. {
  5. public:
  6. Aa( int i= 0){a=i; cout<< "Constructor"<<a<< endl;}
  7. ~Aa(){ cout<< "Destructor"<<a<< endl;}
  8. void print(){ cout<<a<< endl;}
  9. private:
  10. int a;
  11. };
  12. int main()
  13. {
  14. Aa a1(1),a2(2);
  15. a1.print();
  16. a2.print();
  17. return 0;
  18. }
运行结果如下:


2、调试下列程序:
  1. #include<iostream>
  2. using namespace std;
  3. class TPoint
  4. {
  5. public:
  6. TPoint( int x= 0, int y= 0){X=x,Y=y;}
  7. TPoint(TPoint &p);
  8. ~TPoint(){ cout<< "Destructor is called\n";}
  9. int getx(){ return X;}
  10. int gety(){ return Y;}
  11. private:
  12. int X,Y;
  13. };
  14. TPoint::TPoint(TPoint &p)
  15. {
  16. X=p.X;
  17. Y=p.Y;
  18. cout<< "Copy-initialization Constructor is called\n";
  19. }
  20. int main()
  21. {
  22. TPoint p1(4,9);
  23. TPoint p2(p1);
  24. TPoint p3=p2;
  25. TPoint p4,p5( 2);
  26. cout<< "p3=("<<p3.getx()<< ","<<p3.gety()<< ")\n";
  27. return 0;
  28. }

在程序中,将TPoint类的带有两个参数的构造函数进行修改,在函数体内增添下述语句:

      cout<<"Constructor is called\n";

(1)写出程序的输出结果,并解释输出结果;

程序如下:
  1. #include<iostream>
  2. using namespace std;
  3. class TPoint
  4. {
  5. public:
  6. TPoint( int x= 0, int y= 0){X=x,Y=y;}
  7. TPoint(TPoint &p);
  8. ~TPoint(){ cout<< "Destructor is called\n";}
  9. int getx(){ return X;}
  10. int gety(){ return Y;}
  11. private:
  12. int X,Y;
  13. };
  14. TPoint::TPoint(TPoint &p)
  15. {
  16. X=p.X;
  17. Y=p.Y;
  18. cout<< "Constructor is called\n";
  19. cout<< "Copy-initialization Constructor is called\n";
  20. }
  21. int main()
  22. {
  23. TPoint p1(4,9);
  24. TPoint p2(p1);
  25. TPoint p3=p2;
  26. TPoint p4,p5( 2);
  27. cout<< "p3=("<<p3.getx()<< ","<<p3.gety()<< ")\n";
  28. return 0;
  29. }

运行结果如下:


(2)按下列要求进行调试:

       在主函数体内,添加下列说明语句:

      TPoint p4,p5(2);

  1. #include<iostream>
  2. using namespace std;
  3. class TPoint
  4. {
  5. public:
  6. TPoint( int x, int y){X=x,Y=y;}
  7. TPoint(TPoint &p);
  8. ~TPoint(){ cout<< "Destructor is called\n";}
  9. int getx(){ return X;}
  10. int gety(){ return Y;}
  11. private:
  12. int X,Y;
  13. };
  14. TPoint::TPoint(TPoint &p)
  15. {
  16. X=p.X;
  17. Y=p.Y;
  18. cout<< "Copy-initialization Constructor is called\n";
  19. cout<< "Constructor is called\n";
  20. }
  21. int main()
  22. {
  23. TPoint P4,P5( 2);
  24. TPoint p1(4,9);
  25. TPoint p2(p1);
  26. TPoint p3=p2;
  27. cout<< "p3=("<<p3.getx()<< ","<<p3.gety()<< ")\n";
  28. return 0;
  29. }

调试程序会出现什么现象?为什么?如何解决?(提示:对已有的构造函数进行适当修改)结合运行结果分析如何使用不同的构造函数创建不同的对象。

现象:

为什么:因为在类中没有定义不带参数和带一个参数的构造函数;

如何解决:将带两个参数的构造函数改为缺省的构造函数,就是可以将TPoint(int x,int y)改为TPoint(int x=0,int y=0) ; 在运行过程中,TPoint p1(4,9)和TPoint p4,p5(2);调用了构造函数,而TPoint p2(p1)和TPoint p3=p2是使用了拷贝构造函数。如下所示:

  1. //sy3_2.cpp
  2. #include<iostream>
  3. using namespace std;
  4. class TPoint
  5. {
  6. public:
  7. TPoint( int x= 0, int y= 0){X=x,Y=y;}
  8. TPoint(TPoint &p);
  9. ~TPoint(){ cout<< "Destructor is called\n";}
  10. int getx(){ return X;}
  11. int gety(){ return Y;}
  12. private:
  13. int X,Y;
  14. };
  15. TPoint::TPoint(TPoint &p)
  16. {
  17. X=p.X;
  18. Y=p.Y;
  19. cout<< "Copy-initialization Constructor is called\n";
  20. cout<< "Constructor is called\n";
  21. }
  22. int main()
  23. {
  24. TPoint P4,P5( 2);
  25. TPoint p1(4,9);
  26. TPoint p2(p1);
  27. TPoint p3=p2;
  28. cout<< "p3=("<<p3.getx()<< ","<<p3.gety()<< ")\n";
  29. return 0;
  30. }

结果:

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;

写出程序的输出结果,并解释输出结果。

程序如下:

  1. #include<iostream>
  2. using namespace std;
  3. class Heapclass
  4. {
  5. public:
  6. Heapclass( int x);
  7. Heapclass();
  8. ~Heapclass();
  9. private:
  10. int i;
  11. };
  12. Heapclass::Heapclass( int x)
  13. {
  14. i=x;
  15. cout<< "Contstructor is called. "<<i<< endl;
  16. }
  17. Heapclass::Heapclass()
  18. {
  19. cout<< "Default Contstructor is called."<< endl;
  20. }
  21. Heapclass::~Heapclass()
  22. {
  23. cout<< "Default is called."<< endl;
  24. }
  25. int main()
  26. {
  27. Heapclass *pa1,*pa2,*pa3;
  28. pa1= new Heapclass( 4);
  29. pa2= new Heapclass;
  30. pa3= new Heapclass( 5);
  31. if(!pa1||!pa2||!pa3)
  32. {
  33. cout<< "Out of Mcmory!"<< endl;
  34. return 0;
  35. }
  36. cout<< "Exit main"<< endl;
  37. delete pa1;
  38. delete pa2;
  39. delete pa3;
  40. return 0;
  41. }

运行结果如下:


解释: pa1、pa2、pa3中是2个指向类Heapclass的对象指针,在能够赋给它们足够内存的情况下,使用运算符new给它们赋值,同时对它们所指向的对象进行初始化。使用delete释放这三个指针所指向的对象,由于不能够赋给pa1、pa2或pa3足够内存,所以输出“Out of Memory”。

4、请定义一个矩形类(Rectangle),私有数据成员为矩形的长度(len)和宽度(wid),无参构造函数置len和wid为0,有参构造函数置len和 wid为对应形参的值,另外还包括求矩形周长、取矩形面积、取矩形长度和宽度、修改矩形长度和宽度为对应形参的值、输出矩形尺寸等公有成员函数。要求输出矩形尺寸的格式为“length:长度,width:宽度”。
程序如下:
  1. #include<iostream>
  2. using namespace std;
  3. class Rectangle
  4. {
  5. public:
  6. Rectangle()
  7. {
  8. len= 0;
  9. wid= 0;
  10. }
  11. Rectangle( double Len, double Wid)
  12. {
  13. len=Len;
  14. wid=Wid;
  15. }
  16. double Circumference()
  17. {
  18. return 2*(len+wid);
  19. }
  20. double Area()
  21. {
  22. return len*wid;
  23. }
  24. double getl()
  25. {
  26. return len;
  27. }
  28. double getw()
  29. {
  30. return wid;
  31. }
  32. void charge(double a,double b)
  33. {
  34. len=a;
  35. wid=b;
  36. }
  37. void s()
  38. {
  39. cout<< "length:"<<len<< " "<< "width:"<<wid<< endl;
  40. }
  41. private:
  42. int len,wid;
  43. };
  44. int main()
  45. {
  46. Rectangle q;
  47. Rectangle h(5.0,2.0);
  48. cout<< "q的矩形尺寸:"<< endl;
  49. q.s();
  50. cout<< "h的矩形尺寸:"<< endl;
  51. h.s();
  52. cout<< "h的周长:"<<h.Circumference()<< endl;
  53. cout<< "h的面积:"<<h.Area()<< endl;
  54. cout<< "h的长度:"<<h.getl()<< endl;
  55. cout<< "h的宽度:"<<h.getw()<< endl;
  56. h.charge( 8.0, 6.0);
  57. cout<< "修改后的矩形的尺寸:"<< endl;
  58. h.s();
  59. return 0;
  60. }

结果如下:


分析与讨论

  1、类中私有成员的访问权限。

    答:私有成员是被隐藏的数据,只有该类的成员函数或友元函数才可以引用它。

  2、构造函数与析构函数的调用顺序。

    答:构造函数在创建对象的时候被调用,析构函数在释放对象的时候被调用,释放由构造函数分配的内存,构造函数与析构函数的调用顺序正好相反。

  3、何时进行对象初始化?如何进行?(提示:注意分一般对象和堆对象讨论)

    答:一般对象:在对象创建时进行初始化,可以用构造函数或拷贝函数进行初始化。

        堆对象:使用运算符new分配内存,调用构造函数来进行初始化。

实验总结

       本次实验要求我们熟悉类的定义格式和类中成员的访问权限,构造函数与析构函数的调用时机与顺序,掌握对象的定义以及对象的初始化的时机与方法等。类和对象比较好掌握,就是构造函数和析构函数我到现在还不太明白,不知道该怎么运用,请教了几位同学,也自己百度了一下,感觉懵懵懂懂的,不过最后还是把实验做完了,相当的不容易。每做一次实验就会成长一次,也会掌握更多的东西,学到了东西感觉很踏实。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值