zoukankan      html  css  js  c++  java
  • c++构造函数分类说明

    在面向对象编程中,创建对象时系统会自动调用构造函数来初始化对象,构造函数是一种特殊的类成员函数,它有如下特点:

    1. 构造函数的名子必须和类名相同,不能任意命名;
    2. 构造函数没有返回值;
    3. 构造函数可以被重载,但是每次对象创建时只会调用其中的一个;

    我们可以将构造总结为以下几类,不同入参决定调用不同的构造函数,它们分别是普通构造函数 、默认构造函数 、拷贝构造函数 、转换构造函数;下面代码给出了复数类CComplex的多种构造函数以及相关辅助函数;

    1. 普通构造函数

    普通构造函数是最为常见的构造函数,它没有特殊的特点,其函数形参参数可有多个,其函数原型和测试代码如下:

    //普通构造函数原型
    CComplex(int nReal, int nImag);
    
    //测试代码
    //需要指定参数
    CComplex num1(1,1);
    num1.PrintComplex();

    运行结果:

    这里写图片描述

    2. 默认构造函数

    相对于普通构造函数而言,默认构造函数是指用户可以指定实参值,也可以不指定实参值,不指定实参值,系统就使用默认的值,而且默认构造函数只可以有一个,否则有歧义;默认构造函数原型和测试代码如下:

    //默认构造函原型声明
    CComplex();                 //默认构造函数形式1,这里选择形式1
    CComplex(int i=10,int j=10);//默认构造函数形式2
    
    //调用默认构造函数,用户可以不需要指定形参值
    CComplex sum;
    sum.PrintComplex();

    运行结果:

    这里写图片描述

    3. 拷贝构造函数

    拷贝构造函数,也叫做复制构造函数,主要应用于使用一个已存在的对象去初始化一个新对象,使新对象的属性和该对象保持一致

    若用户未定义拷贝构造函数,编译器就自动提供一个默认的复制构造函数,其作用仅是简单地复制类中的每个数据成员;为了安全起见,类设计者需要提供拷贝构造函数;

    拷贝构造函数一般形式:

    类名(const 类名& 对象名)

    形如:CComplex(const CComplex& srcObj)

    在以下三种情况下,拷贝构造函数将被调用;

    1. 建立新对象

    使用一个已存在对象num,初始化即将要被创建的新对象,可以有以下两种形式:

    CComplex num1(num); //形式1
    CComplex num2=num;  //形式2

    运行结果:

    这里写图片描述

    2. 函数形参为类对象

    在函数调用时需要将实参对象完整地传递给形参,系统将默认调用拷贝构造函数,建立一个实参的拷贝,这样形参对象和实参对象将具有相同的属性值;

    需要注意的是,仅形参是按值传递时才会进行对象拷贝,若是传递引用,不会进行对象拷贝,

    形如:

    //按值传递,复制对象
    static void TransByValue(CComplex obj)
    //传递引用,不复制对象
    static void TransByRefence(const CComplex& obj)

    测试代码如下:

    CComplex num(8,8);
    cout << "test case result:
    " << endl;
    
    cout << "test case by refence:
    " << endl;  
    CComplex::TransByValue(num);
    
    cout << "test case by refence:
    " << endl;
    CComplex::TransByRefence(num);

    运行结果:

    这里写图片描述

    3. 函数返回值是类对象

    当一个函数返回值是一个类对象时,在该函数返回调用处时,系统会将函数中的对象复制一份到别的地方,即使返回值没有被使用;

    形如:

    static CComplex GetObj()
    {
      CComplex ret(10,10);  
      return ret;
    }

    测试代码:

    //直接拷贝函数中的对象来初始化新对象num
    CComplex num =  CComplex::GetObj();
    
    //函数返回值进行对象拷贝
    CComplex::GetObj();

    运行结果:

    这里写图片描述

    4. 转换构造函数

    转换构造函数的作用是将一个其他类型的数据转换为一个类的对象。转换构造函数也是一种构造函数,它遵循构造函数的一般原则,我们通常把仅有一个参数的构造函数用作类型转换,所把它称为转换构造函数。

    转换构造函数中的类型数据可以是普通类型,也可以是类类型,其一般形式如下:

    类名(指定类型的数据)

    形如:

    //转换构造函数
    CComplex(int nReal)

    测试代码:

    //定义对象
    CComplex num1(1,1);
    
    cout << "test case result:
    " << endl;
    //num1+2 =》
    //step1:将整型数2转换为CComplex临时对象 调用转换构造函数
    //step2:进行operator+运算符重载
    //step3:运算符重载返回类对象
    CComplex::TransByRefence(num1 + 2);

    运行结果:

    这里写图片描述

    5. 对象拷贝和对象赋值的区别

    对象的赋值是对一个已经存在的对象进行重新赋值,因此必须先定义被赋值的对象,才能进行赋值;

    而对象的拷贝是在从无到有建立一个新对象,并使这个新对象和已有对象完全相同;

    例如:

    CComlex num1(1,1);
    CCompex num2(2,2);
    //对象赋值 使对象num2的值和对象num1一致,调用进行operator=运算符重载
    num2 = num1;
    
    //对象拷贝,利用对象num2创建新对象num3;
    CCompex num3 = num2;

    6. CCompex 类实现代码

    class CComplex
    {
    public:
    
        //普通构造函数
        CComplex(int nReal, int nImag):m_nReal(nReal),m_nImag(nImag)
        {
            cout << "common constructor function" << endl;
        }
        //默认构造函数 默认构造函仅有一个
        CComplex():m_nReal(10),m_nImag(10)
        {
            cout << "default constructor function" << endl;
        }
    
        //拷贝构造函数或者复制构造函数
        CComplex(const CComplex& srcObj)
            :m_nReal(srcObj.m_nReal)
            ,m_nImag(srcObj.m_nImag)
        {
            cout << "copy constructor function" << endl;
        }
    
        //转换构造函数,也可认为是普通构造函数,需要看上下文
        CComplex(int nReal):m_nReal(nReal),m_nImag(0)
        {
            cout << "convert constructor function" << endl;
        }
    
        //赋值操作运算符
        CComplex& operator=(const CComplex& srcObj)
        {
            cout << "operate= function" << endl;
    
            //防止自我赋值,eg:a = a;
            if (this == &srcObj)
           {
               return *this;
           }
    
           this->m_nReal = srcObj.m_nReal;
           this->m_nImag = srcObj.m_nImag;
           return *this;
        }
    
        //析构函数
        ~CComplex(){}
    
    public:
        //+操作运算符  辅助函数,用于说明转换构造函数
        friend CComplex operator+(const CComplex& srcObj1, const CComplex& srcObj2)
        {
            cout << "operate+ function" << endl;
            int nReal = srcObj1.m_nReal+srcObj2.m_nReal;
            int nImag = srcObj1.m_nImag+srcObj2.m_nImag;
            //无名构造函数
            return CComplex(nReal, nImag);
        }
    
        void PrintComplex() const
        {
            cout << "real: " << m_nReal << " " 
                 << "imag: " << m_nImag 
                 << "
    " 
                 <<endl;
        }
        //按值传递,注意不是对象引用
        static void TransByValue(CComplex obj)
        {
          obj.PrintComplex();
        }
    
        static void TransByRefence(const CComplex& obj)
        {
            obj.PrintComplex();
        }
    
        static CComplex GetObj()
        {
            CComplex ret(10,10);
            return ret;
        }
    
    private:
        int m_nReal;
        int m_nImag;
    };
  • 相关阅读:
    LeetCode 1122. Relative Sort Array (数组的相对排序)
    LeetCode 46. Permutations (全排列)
    LeetCode 47. Permutations II (全排列 II)
    LeetCode 77. Combinations (组合)
    LeetCode 1005. Maximize Sum Of Array After K Negations (K 次取反后最大化的数组和)
    LeetCode 922. Sort Array By Parity II (按奇偶排序数组 II)
    LeetCode 1219. Path with Maximum Gold (黄金矿工)
    LeetCode 1029. Two City Scheduling (两地调度)
    LeetCode 392. Is Subsequence (判断子序列)
    写程序判断系统是大端序还是小端序
  • 原文地址:https://www.cnblogs.com/jinxiang1224/p/8468239.html
Copyright © 2011-2022 走看看