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. 查看对象的成员地址,查看对象的地址。
     #include<iostream>
    using namespace std;
    class rectangle{
    public:
    rectangle(double x=2.0,double y=4.0);
    rectangle(rectangle &r);//复制构造函数:类名+&对象名
    ~rectangle();
    double calarea(double a,double b);
    double getx(){
    return x;
    }
    double gety(){
    return y;
    }
    double * ptr_x()//查看地址
    {
    double *x_ptr = &y;
    return x_ptr;
    }
    private:
    double x;
    double y;
    }; double rectangle::calarea(double a,double b){
    x=a;
    y=b;
    return a*b;
    }
    rectangle::rectangle(double a,double b){
    x=a;
    y=b; //在声明处定义之后,在此处如果没有将值赋给x,y,那么x,y将不会有初值,使用getx()得到的将是一个默认分配的地址 }
    rectangle::rectangle(rectangle &r){
    x=r.x;
    y=r.y;
    cout<<"复制构造被调用"<<endl;
    }
    rectangle::~rectangle(){ }
    //测试复制函数被调用的第二种情况
    void f(rectangle r){
    cout<<"值传递的情况"<<endl;
    }
    void f2(rectangle &r){
    cout<<"引用传递的情况"<<endl;
    }
    //测试复制函数被调用的第三种情况
    rectangle g(){
    rectangle a(,);
    return a;
    }
    int main(){
    rectangle r,r2(,),r4; cout<<"默认参数求面积:"<<r.calarea(r.getx(),r.gety())<<endl;//如果嵌套调用会出错; ques:类的私有成员能不能当做形参;
    cout<<"初始化后求面积:"<<r.calarea(,)<<endl; cout<<r2.calarea(,)<<endl;
    rectangle r3(r2);//用类的一个对象去初始化另一个对象可以调用复制构造函数
    cout<<"利用对象初始化对象求面积:"<<r3.calarea(r2.getx(),r2.gety())<<endl;
    //r4(&r2);//qus:想利用引用传递?对象利用对象初始化不能使用引用传值? f(r2); //对象做形参,值传递会调用复制构造
    f2(r2); //地址传递不会调用复制构造
    //??为什么值传递和地址传递在调用复制构造函数会0有差别? cout<<"r4地址:"<<r4.ptr_x()<<endl;
    r4=g();//测试有没有调用复制构造函数;
    cout<<r4.getx()<<endl;
    //想查看对象地址,怎么办
    cout<<"r4返回调用后的地址:"<<r4.ptr_x()<<endl;
    return ; }

    rectangle

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

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

  1. 类的初始化与类的赋值
  2. 默认参数函数和构造函数的区别
  3. 代码实现及其截图
     #include<iostream>
    using namespace std;
    class Complex{
    public:
    Complex(double x0=,double y0=){
    x=x0;y=y0;
    }
    ~Complex();
    Complex(Complex &c){
    x=c.x;
    y=c.y;
    }
    double getx(){
    return x;
    }
    double gety(){
    return y;
    }
    Complex add(Complex b);
    Complex jian(Complex a);
    void show(); private:
    double x;
    double y;
    };
    Complex::~Complex(){
    }
    Complex Complex::add(Complex b){ x=x+b.x;
    y=y+b.y; }
    Complex Complex::jian(Complex a){
    x=x-a.x;
    y=y-a.y;
    }
    void Complex::show(){
    cout<<"当前值:"<<x<<"+"<<"("<<y<<")"<<"i"<<endl;
    } int main(){
    Complex c(,),d;//1.初始化对象,一定要为成员赋予初值吗
    d=4.5;
    c.show();
    c.add(d);
    c.show();
    return ;
    }

    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;
      }

【C++/实验三】类和对象的更多相关文章

  1. 【C++ 实验5 类和对象】

    1. #include <iostream> #include <vector> #include <string> using namespace std; // ...

  2. c++实验3类和对象

     实 验 3: part 1:验证 part 2:graph #include <iostream> #include "graph.h" using namespac ...

  3. C++ 实验3 类和对象

    Part 2 #ifndef GRAPH_H #define GRAPH_H class Graph { public: Graph(char ch, int n); void draw(); pri ...

  4. IOS基础之 (三) 类的声明和对象的创建

    一 OC类的声明和实现语法 1.接口的声明 @interface NewClassName: ParentClassName { 实例变量 ... } 方法的声明 ... @end //...表示省略 ...

  5. java总结第三次//类和对象2、3

    四.类和对象2 主要内容:Java类的继承.方法的重写.覆盖.访问控制.super 关键字.多态性及其应用 1.继承 要求:Java只支持单继承,不允许多重继承 一个子类只能有一个父类 一个父类可以派 ...

  6. python-面向对象(三)——类的特殊成员

    类的特殊成员 1. __doc__     表示类的描述信息 class Foo: """ 描述类信息,这是用于看片的神奇 """ def ...

  7. python cookbook第三版学习笔记十:类和对象(一)

    类和对象: 我们经常会对打印一个对象来得到对象的某些信息. class pair:     def __init__(self,x,y):         self.x=x         self. ...

  8. PHP7语法知识(三):时间与日期、表单、类与对象、正则表达式、错误异常处理、图像处理

    时间与日期 一.设置时区 1.在配置文件中设置: 2.通过data_default_timezone_set函数在文件中设置: 二.获取当前时间 三.常用时间处理方法 1.格式化时间显示: 2.计算时 ...

  9. Kotlin基础(三)类、对象和接口

    类.对象和接口 一.定义类的继承结构 一)Kotlin中的接口 Kotlin的接口与Java8中相似,它们可以包含抽象方法的定义以及非抽象方法的实现,但它们不能包含任何状态. interface Cl ...

随机推荐

  1. kettle 6.1 按时间循环增量抽取数据

    场景:假设有一张表数据量很大,需要按一个时间来循环增量抽取 方法:主要是通过JOB自身调用,实现循环调用,类似于 函数自调用 的循环. 1.JOB全图: 2.获取增量时间,并设置增量时间环境变量 3. ...

  2. 【Spring】Springboot监听器,启动之后初始化工作

    package com.laplace.laplace.common.starter.config; import java.io.IOException; import org.slf4j.Logg ...

  3. [Linux] - Windows与Linux网络共享文件夹挂载方法

    Windows与Linux网络SMB方式文件夹共享挂载 本示例系统: Windows 2003+ Linux-Centos/Ubuntu 本示例全为命令行操作,如何使用Windows.Linux命令行 ...

  4. ORACLE 从一个实例迁移到另外一个实例实战记录

    .schema1到schema2的迁移 Oracle 从一个用户expdp导出再impdp导入到还有一个用户,能够使用REMAP_SCHEMA=user1:user2来实现: 假设想导入的用户已经存在 ...

  5. golang 使用pprof和go-torch做性能分析

    软件开发过程中,项目上线并不是终点.上线后,还要对程序的取样分析运行情况,并重构现有的功能,让程序执行更高效更稳写. golang的工具包内自带pprof功能,使找出程序中占内存和CPU较多的部分功能 ...

  6. 使用多个项目生成Xml文件来显示帮助文档

    终于到这了,我们首先将Product单独作为一个项目 WebAPI2PostMan.WebModel 并引用他,查看文档如下. 你会发现,你的注释也就是属性的描述没有了.打开App_Data/XmlD ...

  7. Tomcat 部署多个项目出现错误

    有时,我们会遇到部署同样项目可是不同版本号来回切换的问题.可是有时就是莫名奇异的会起不来. 也没太多时间去解决这些问题,所以就又一次把纯净版的Tomcat部署进去就能够了. 我想非常有可能就是Tomc ...

  8. 【理论面试篇】收集整理来自网络上的一些常见的 经典前端、H5面试题 Web前端开发面试题

    ##2017.10.30收集 面试技巧 5.1 面试形式 1)        一般而言,小公司做笔试题:大公司面谈项目经验:做地图的一定考算法 2)        面试官喜欢什么样的人 ü  技术好. ...

  9. mysql 动态增加列,查找表中有多少列,具体什么列。 通过JSON生成mysql表 支持子JSON

    好消息, 程序员专用早餐机.和掌柜说 ideaam,可以节省20元. 点击链接  或復·制这段描述¥k3MbbVKccMU¥后到淘♂寳♀ 或者 淘宝扫码 支持下同行哈 ---------------- ...

  10. 【原创 Hadoop&Spark 动手实践 9】Spark SQL 程序设计基础与动手实践(上)

    [原创 Hadoop&Spark 动手实践 9]SparkSQL程序设计基础与动手实践(上) 目标: 1. 理解Spark SQL最基础的原理 2. 可以使用Spark SQL完成一些简单的数 ...