实验3 构造函数与析构函数(P279)

实验目的和要求

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

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

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

实验内容

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

  1. <span style="font-size:18px;">//sy3_1.cpp  
  2. #include<iostream>  
  3. using namespace std;  
  4. class Aa  
  5. {  
  6.   public:  
  7.       Aa(int i=0){a=i;cout<<"Constructor"<<a<<endl;}  
  8.       ~Aa(){cout<<"Destructor"<<a<<endl;}  
  9.       void print(){cout<<a<<endl;}  
  10.   private:  
  11.     int a;  
  12. };  
  13. int main()  
  14. {  
  15.     Aa a1(1),a2(2);  
  16.     a1.print();  
  17.    cout<<a2.a<<endl;//ERROR  
  18.     return 0;  
  19. }</span>  
//sy3_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
    return 0;
}

运行结果如下:


修改程序如下:

  1. <span style="font-size:18px;">//sy3_1.cpp  
  2. #include<iostream>    
  3. using namespace std;    
  4. class Aa    
  5. {    
  6.   public:    
  7.       Aa(int i=0){a=i;cout<<"Constructor"<<a<<endl;}    
  8.       ~Aa(){cout<<"Destructor"<<a<<endl;}    
  9.       void print(){cout<<a<<endl;}    
  10.   private:    
  11.     int a;    
  12. };    
  13. int main()    
  14. {    
  15.     Aa a1(1),a2(2);    
  16.     a1.print();    
  17.     a2.print();    
  18.     return 0;    
  19. }</span>  
//sy3_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();  
    a2.print();  
    return 0;  
}

正确程序运行结果如下:



2、调试下列程序。

  1. <span style="font-size:18px;">//sy3_2.cpp  
  2. #include<iostream>  
  3. using namespace std;  
  4. class TPoint  
  5. {  
  6. public:  
  7.     TPoint(int x,int y){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. }  
  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. }</span>  
//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";
}
int main()
{
    TPoint p1(4,9);
    TPoint p2(p1);
    TPoint p3=p2;
    TPoint p4,p5(2);
    cout<<"p3=("<<p3.getx()<<","<<p3.gety()<<")\n";
    return 0;
}

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

cout<<"Constructor is called.\n";

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

修改程序如下:

  1. <span style="font-family:SimSun;font-size:18px;">//sy3_2.cpp  
  2. #include<iostream>  
  3. using namespace std;  
  4. class TPoint  
  5. {  
  6. public:  
  7.     TPoint(int x,int y){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 p1(4,9);  
  25.     TPoint p2(p1);  
  26.     TPoint p3=p2;  
  27.     cout<<"p3=("<<p3.getx()<<","<<p3.gety()<<")\n";  
  28.     return 0;  
  29. }</span>  
//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;
    cout<<"p3=("<<p3.getx()<<","<<p3.gety()<<")\n";
    return 0;
}


原程序运行结果如下:


修改后的程序运行结果如下:


输出结果解释:


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

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

TPoint  P4,P5(2);

  1. //sy3_2.cpp  
  2. #include<iostream>  
  3. using namespace std;  
  4. class TPoint  
  5. {  
  6. public:  
  7.     TPoint(int x,int y){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. }  
//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 P4,P5(2);
    TPoint p1(4,9);
    TPoint p2(p1);
    TPoint p3=p2;
    cout<<"p3=("<<p3.getx()<<","<<p3.gety()<<")\n";
    return 0;
}
运行结果如下:


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

出现的现象:


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

如何解决:将带两个参数的构造函数改为缺省的构造函数,就是可以将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. }  
//sy3_2.cpp
#include<iostream>
using namespace std;
class TPoint
{
public:
    TPoint(int x=0,int y=0){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 P4,P5(2);
    TPoint p1(4,9);
    TPoint p2(p1);
    TPoint p3=p2;
    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;

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

原程序如下:

  1. <span style="font-family:SimSun;font-size:18px;">//程序Li3_11.cpp  
  2. //new和delete的用法  
  3. #include<iostream>    
  4. using namespace std;    
  5. class Heapclass    
  6. {    
  7.     public:    
  8.     Heapclass(int x);    
  9.     Heapclass();    
  10.     ~Heapclass();    
  11.     private:    
  12.     int i;    
  13. };    
  14. Heapclass::Heapclass(int x)    
  15. {    
  16.     i=x;    
  17.     cout<<"Contstructor is called."<<i<<endl;    
  18. }    
  19. Heapclass::Heapclass()    
  20. {    
  21. cout<<"Default Contstructor is called."<<endl;    
  22. }    
  23. Heapclass::~Heapclass()    
  24. {    
  25. cout<<"Default is called."<<endl;    
  26. }    
  27. int main()    
  28. {    
  29. Heapclass *pa1,*pa2,*pa3;    
  30. pa1=new Heapclass(4);    
  31. pa2=new Heapclass;    
  32. pa3=new Heapclass(5);    
  33. if(!pa1||!pa2||!pa3);    
  34. {    
  35.     cout<<"Out of Memory!"<<endl;    
  36.     return 0;    
  37. }    
  38. cout<<"Exit main"<<endl;    
  39. delete pa1;    
  40. delete pa2;    
  41. delete pa3;    
  42. return 0;    
  43. }</span>  
//程序Li3_11.cpp
//new和delete的用法
#include<iostream>  
using namespace std;  
class Heapclass  
{  
    public:  
    Heapclass(int x);  
    Heapclass();  
    ~Heapclass();  
    private:  
    int i;  
};  
Heapclass::Heapclass(int x)  
{  
    i=x;  
    cout<<"Contstructor is called."<<i<<endl;  
}  
Heapclass::Heapclass()  
{  
cout<<"Default Contstructor is called."<<endl;  
}  
Heapclass::~Heapclass()  
{  
cout<<"Default 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中是2个指向类Heapclass的对象指针,在能够赋给它们足够内存的情况下,使用运算符new给它们赋值,同时对它们所指向的对象进行初始化。使用delete释放这三个指针所指向的对象,由于不能够赋给pa1、pa2或pa3足够内存,所以输出“Out of Memory”。

4、请定义一个矩形类(Rectangle),私有数据成员为矩形的长度(len)和宽度(wid),无参构造函数置len和wid为0,有参构造函数置len和wid为对应形参的值,另外还包括求矩形周长、取矩形面积、取矩形长度和宽度、修改矩形长度和宽度为对应形参的值、输出矩形尺寸等公有成员函数。要求输出矩形尺寸的格式为“length:长度,width:宽度”。(sy3_3.cpp)

  1. //sy3_4.cpp  
  2. #include<iostream>  
  3. using namespace std;  
  4. class Rectangle  
  5. {  
  6. public:  
  7.    Rectangle()  
  8.    {  
  9.        len=0;  
  10.        wid=0;  
  11.    }  
  12.    Rectangle(double Len,double Wid)  
  13.    {  
  14.        len=Len;  
  15.        wid=Wid;  
  16.     }  
  17.    double Circumference()  
  18.    {  
  19.        return 2*(len+wid);  
  20.     }  
  21.    double Area()  
  22.    {  
  23.        return len*wid;  
  24.     }  
  25.    double getl()  
  26.    {  
  27.        return len;  
  28.     }  
  29.    double getw()  
  30.    {  
  31.        return wid;  
  32.     }  
  33.    void charge(double a,double b)  
  34.    {  
  35.        len=a;  
  36.        wid=b;  
  37.     }  
  38.    void s()  
  39.    {  
  40.        cout<<"length:"<<len<<"  "<<"width:"<<wid<<endl;  
  41.     }  
  42. private:  
  43.     int len,wid;  
  44. };  
  45. int main()  
  46. {  
  47.   Rectangle q;  
  48.   Rectangle h(5.0,2.0);  
  49.   cout<<"q的矩形尺寸:"<<endl;  
  50.   q.s();  
  51.   cout<<"h的矩形尺寸:"<<endl;  
  52.   h.s();  
  53.   cout<<"h的周长:"<<h.Circumference()<<endl;  
  54.   cout<<"h的面积:"<<h.Area()<<endl;  
  55.   cout<<"h的长度:"<<h.getl()<<endl;  
  56.   cout<<"h的宽度:"<<h.getw()<<endl;  
  57.   h.charge(8.0,6.0);  
  58.   cout<<"修改后的矩形的尺寸:"<<endl;  
  59.    h.s();  
  60.    return 0;  
  61. }  
//sy3_4.cpp
#include<iostream>
using namespace std;
class Rectangle
{
public:
   Rectangle()
   {
       len=0;
       wid=0;
   }
   Rectangle(double Len,double Wid)
   {
       len=Len;
       wid=Wid;
    }
   double Circumference()
   {
       return 2*(len+wid);
    }
   double Area()
   {
       return len*wid;
    }
   double getl()
   {
       return len;
    }
   double getw()
   {
       return wid;
    }
   void charge(double a,double b)
   {
       len=a;
       wid=b;
    }
   void s()
   {
       cout<<"length:"<<len<<"  "<<"width:"<<wid<<endl;
    }
private:
    int len,wid;
};
int main()
{
  Rectangle q;
  Rectangle h(5.0,2.0);
  cout<<"q的矩形尺寸:"<<endl;
  q.s();
  cout<<"h的矩形尺寸:"<<endl;
  h.s();
  cout<<"h的周长:"<<h.Circumference()<<endl;
  cout<<"h的面积:"<<h.Area()<<endl;
  cout<<"h的长度:"<<h.getl()<<endl;
  cout<<"h的宽度:"<<h.getw()<<endl;
  h.charge(8.0,6.0);
  cout<<"修改后的矩形的尺寸:"<<endl;
   h.s();
   return 0;
}
运行结果如下:



分析与讨论

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

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

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

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

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

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

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

实验总结

    在这次实验中我学会了构造函数与析构函数的使用,掌握了它们的调用方法与调用顺序,当然对类的定义格式和类中成员的访问权限也更加的熟悉,同时还掌握了拷贝函数的使用方法,虽然对知识点的掌握不是很牢固,在编写程序时因为对知识点不能熟练运用,会导致不知道该怎么去构造这个程序,头脑里没有清晰地思路,在写程序前先不要着急写,应该先弄清楚所写得程序要运用到哪些基本知识,自己如果对某个知识不熟悉就得巩固一下,再按照题目要求弄清这个程序的思路,我相信通过长期反复的训练最终也会熟能生巧。

    这次实验的过程不是非常的顺利,在编写程序是,由于疏忽大意将private的p写成大写的,并且把文件格式存错了,本该是.cpp为后缀的,存成了.c为后缀,导致一直运行都出现错误,在一次次的排查之后才找到了问题的出处,所以,在写程序是一定要细心,只有细心才能有所所获。




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值