zoukankan      html  css  js  c++  java
  • 【C++/实验三】类和对象

    1.定义一个矩形类,有长,宽两个属性,有成员函数计算矩形的面积。

    在该矩形类中,我做了5个主要的测试。

    1. 构造函数带默认值参数,利用默认值参数计算矩形面积:rectangle(double x=2.0,double y=4.0);    cout<<r.calarea(r.getx(),r.gety())<<endl;  
    2. 测试复制构造函数什么时候被调用:
      1. 用类的一个对象去初始化另一个对象的时候被调用
      2. 如果参数的形参是类的对象,调用函数时,形参和实参相结合时被调用
      3. 函数的返回值是类的对象时被调用。
    3. 查看对象的成员地址,查看对象的地址。
       1 #include<iostream>
       2 using namespace std;
       3 class rectangle{
       4     public:
       5     rectangle(double x=2.0,double y=4.0);
       6     rectangle(rectangle &r);//复制构造函数:类名+&对象名 
       7     ~rectangle();
       8     double calarea(double a,double b);
       9     double getx(){
      10         return x;
      11     }
      12     double gety(){
      13         return y;
      14     }
      15     double * ptr_x()//查看地址 
      16 {
      17     double *x_ptr = &y;
      18     return x_ptr;
      19 }
      20     private:
      21         double x;
      22         double y;
      23 }; 
      24     
      25   double  rectangle::calarea(double a,double b){
      26         x=a;
      27         y=b;
      28         return a*b;
      29     }
      30     rectangle::rectangle(double a,double b){
      31         x=a;
      32         y=b;  //在声明处定义之后,在此处如果没有将值赋给x,y,那么x,y将不会有初值,使用getx()得到的将是一个默认分配的地址 
      33         
      34     }
      35     rectangle::rectangle(rectangle &r){
      36         x=r.x;
      37         y=r.y;
      38         cout<<"复制构造被调用"<<endl; 
      39     } 
      40     rectangle::~rectangle(){
      41         
      42     }
      43 //测试复制函数被调用的第二种情况 
      44     void f(rectangle r){
      45         cout<<"值传递的情况"<<endl; 
      46     } 
      47     void f2(rectangle &r){
      48         cout<<"引用传递的情况"<<endl; 
      49     } 
      50 //测试复制函数被调用的第三种情况
      51    rectangle g(){
      52         rectangle a(8,9);
      53         return a;
      54     }  
      55     int main(){
      56         rectangle r,r2(5,6),r4;
      57         
      58         cout<<"默认参数求面积:"<<r.calarea(r.getx(),r.gety())<<endl;//如果嵌套调用会出错; ques:类的私有成员能不能当做形参; 
      59         cout<<"初始化后求面积:"<<r.calarea(4,5)<<endl;
      60         
      61         cout<<r2.calarea(5,6)<<endl;
      62         rectangle r3(r2);//用类的一个对象去初始化另一个对象可以调用复制构造函数 
      63         cout<<"利用对象初始化对象求面积:"<<r3.calarea(r2.getx(),r2.gety())<<endl;
      64         //r4(&r2);//qus:想利用引用传递?对象利用对象初始化不能使用引用传值?
      65         
      66         
      67         f(r2); //对象做形参,值传递会调用复制构造 
      68         f2(r2); //地址传递不会调用复制构造
      69         //??为什么值传递和地址传递在调用复制构造函数会0有差别? 
      70         
      71         
      72         cout<<"r4地址:"<<r4.ptr_x()<<endl;
      73         r4=g();//测试有没有调用复制构造函数; 
      74         cout<<r4.getx()<<endl; 
      75         //想查看对象地址,怎么办 
      76         cout<<"r4返回调用后的地址:"<<r4.ptr_x()<<endl; 
      77         return 0; 
      78         
      79     } 
      rectangle

    2.定义一个复数类,使得下面的代码能够工作。

    在该Complex类中,我觉得考查了两方面:

    1. 类的初始化与类的赋值
    2. 默认参数函数和构造函数的区别
    3. 代码实现及其截图
       1 #include<iostream>
       2 using namespace std;
       3 class Complex{
       4     public:
       5         Complex(double x0=0,double y0=0){ 
       6             x=x0;y=y0;
       7         }
       8         ~Complex();
       9         Complex(Complex &c){
      10             x=c.x;
      11             y=c.y;
      12         }
      13         double getx(){
      14             return x;
      15         }
      16         double gety(){
      17             return y;
      18         }
      19         Complex add(Complex b);
      20         Complex jian(Complex a);
      21         void show();
      22         
      23         
      24     private:
      25         double x;
      26         double y;
      27 };
      28     Complex::~Complex(){
      29     }
      30     Complex    Complex::add(Complex b){
      31         
      32         x=x+b.x;
      33         y=y+b.y;
      34         
      35     }
      36     Complex    Complex::jian(Complex a){
      37         x=x-a.x;
      38         y=y-a.y;
      39     }
      40     void Complex::show(){
      41         cout<<"当前值:"<<x<<"+"<<"("<<y<<")"<<"i"<<endl;
      42     }
      43 
      44 
      45 int main(){
      46     Complex c(3,5),d;//1.初始化对象,一定要为成员赋予初值吗 
      47     d=4.5;
      48     c.show();
      49     c.add(d);
      50     c.show();
      51     return 0;
      52 }
      Complex

       

     3.实验小结(蓝色字体为自己对自己问题的回答桃红则是没有解决的问题

    1. 为什么值传递和地址传递在调用复制构造函数上会有差别?  因为值传递传递的值是由复制构造函数复制之后的副本,地址与之前的对象初始化的值不一样。而地址传递是传递最开始初始化的地址,还是最初的对象。
    2. 函数的返回值是类的对象时被调用。这是书上写的,但是为什么我在测试的时候并没有调用呢(用的书上的实例)?
      • 考虑到编译器的问题,我分别尝试了devC++4.5版本和codeblock,结果都是没有调用
      • 进行百度之后,发现有人遇到同样的问题:原因是,C++做了优化,返回值为对象时,不再产生临时对象,因而不再调用复制构造函数。
      • 什么是命名返回值优化?
        • 定义:如果一个函数的返回值为一个对象,返回语句的执行过程是,将这个对象从当前函数的局部作用域(当前函数的栈空间),拷贝到返回区,使得调用者可以访问。程序从当前函数返回到上一层,就是该函数的调用语句,通过访问返回区的对象,来执行调用语句所在的一整个语句。  优点:当这个函数中所有的返回语句全部是这一个对象的话,那么,命名返回值优化的作用就是,在这个对象建立的时候,直接在返回区建立。这样就使得函数返回时不需要调用拷贝构造函数了,减少了一个对象的创建与销毁过程。推荐参考博客:https://blog.csdn.net/sad_sugar/article/details/50569434
      • 如果要进行调用复制构造函数怎么停止编译器优化呢?
        • 使用codeblock,打开settings->Compiler...,在Global compiler settings部分,选择Other options,在文本框中写入“-fno-elide-constructors” 如图
    3. 初始化对象的时候,一定要赋值吗?

      1. 首先理解什么是初始化:声明一个变量时,为变量进行初始化,就是在分配内存单元的同时,在其中写入变量的初始值。

      2. 构造函数的原理:类的对象的复杂性使得不能直接初始化,因此设置初始化程序的接口,并具有自动调用机制,这就是构造函数。   作用:在对象被创建时利用特定的值构造对象,将对象初始化为一个特定的状态。
      3. 所以初始化对象肯定是使得对象有一个特定的值。但是我的问题在:为什么有些初始化对象可以是:colok a,有些是colok a(9,10,11),原因是:colok a,构造函数为coloc(int x=0,int y=0,int z=0),而coloc a(9,10,11)的构造函数既可以有默认值,也可以是没有赋有默认值的coloc(int x,int y,int z).
    4.  构造函数和带默认形参值的函数的区别:
      1. 带默认形参值的函数可以带有默认值的形参和没有默认值的形参,例如:add(int x,int y=5,int z=6),但是在构造函数中不允许这样。上述例子在类中会报错。
    5. 怎样查看对象的地址?(已解决)
      1. 我的想法是:设定一个指针p,使p=&a,(a为对象)。但是操作过程中最大的问题就是p应该是什么类型的呢?尝试了类名,double等都不行。                          //应该使用 类名 *p=&对象,cout<<p<<endl;在写程序的时候漏掉了*;(*p)操作是这样一种运算,返回p 的值作为地址的那个空间的取值。(&p)则是这样一种运算,返回当时声明p 时开辟的地址。
      2. 在类中写一个函数

        double * ptr_x()//查看成员地址
        {
        double *x_ptr = &y;
        return x_ptr;
        }          

  • 相关阅读:
    2020.2.14
    2020.2.13
    2020.2.12
    2020.2.11
    org.apache.ibatis.binding.BindingException: Parameter '0' not found. Available parameters are [arg1, arg0, param1, param2]
    springboot 项目报错问题的解决
    使用IDEA搭建一个简单的SpringBoot项目——详细过程
    从零开始实现一个简易的Java MVC框架(三)--实现IOC
    使用IDEA创建JavaWeb项目 部署本地tomcat并运行
    ChromePassword
  • 原文地址:https://www.cnblogs.com/yitou13/p/8727350.html
Copyright © 2011-2022 走看看