zoukankan      html  css  js  c++  java
  • C++:构造函数与析构函数

    构造函数

    类的对象都是由构造函数产生的
    同 Java 一样,若类未定义构造函数,则会产生默认构造函数(无参构造函数)

    class complex{
    	private:
    		double real, image;
    	public:
    		complex(){}
    		complex(double r){ real = r; image = 0; }
    		complex(double r, double i){  }
    		complex(complex c1, complex c2){
    			real = c1.real + c2.real;
    			image = c1.image + c2.image;
    		}
    };
    

    构造函数可以使用初始化列表简写

    complex (double r, double i) : real(r), image(i){}//用r初始化real,用i初始化image
    

    构造函数的调用

    complex c1;//complex()
    complex c2();//complex()
    complex c3(5);//complex(5)
    complex *c4p = new complex(5, 6);//complex(5, 6)
    
    complex cs1[3] = {1, complex(3,2) };
    //cs1[0] -> complex(1) cs1[1] -> complex(3, 2) cs1[2] -> complex()
    
    complex *csp1[2] = new complex[2];//均调用无参构造函数
    
    complex *csp2[2] = {};//未创建任何对象
    
    complex *csp3[3] = {new complex(1), new complex()};
    //指针数组,前两个元素使用complex(1)、complex(),最后一个指针未初始化,仅创建了两个对象
    

    复制构造函数

    一个类一定有且仅有一个复制构造函数
    形如 X::X(X &x)X::X(const X &x),参数必须是引用类型
    若未自定义复制构造函数,编译器自动添加默认的构造函数
    构造函数的作用类似 Java 中 Object.clone()

    作用场景

    • 用一个对象去初始化同类的另一个对象时
      Complex c2(c1);
      Complex c2 = c1;(因为是声明语句,所以调用了复制构造函数)
    • 如果某个函数的参数为类对象,该函数调用时将使用复制构造函数初始化该参数
    • 当函数的返回值是一个类的对象时,返回的对象是通过以函数返回的对象作为参数
      调用复制构造函数产生的(无法返回一个局部变量)

    对象间的赋值,并不会调用复制构造函数

    此外,为避免调用复制构造函数初始化形参的开销,在合适的时候使用引用及引用常量类型的参数


    转换构造函数

    只有一个参数且不是复制构造函数的构造函数,一般可视作转换构造函数
    在需要的时候,编译系统会自动调用转换构造函数,制造一个无名的临时对象

    临时对象就是不可见的匿名对象,也叫无名对象,没有名字故无法继续使用
    仅在运行中需要时生成,使用后析构

    临时对象在 “full expression” 结束时被析构,即 生成临时对象的最大表达式结束处即是临时对象的析构处

    complex::complex(double r){ real = r; image = 0;}//double型转换为complex类型
    complex c = 5;//complex(5)
    c = 9;//调用complex(9)
    complex c2(3);//complex(3)
    

    转换构造函数的作用是实现类型的转换,分为隐式转换和显式转换
    上面 c = 9即为隐式转换
    使用 explicit 关键字表明禁止其修饰的构造函数进行隐式的类型转换

    c = complex(9);//函数仍然可以显式调用
    

    隐式转换常常会导致迷惑行为,需要小心使用

    string str = 'a';//实际上调用的是 string(int size), 可能误以为调用了string(char c)等
    

    析构函数

    名字与类名相同,在函数名前加 ~,一个类最多只有一个析构函数
    编译器默认生成空实现的析构函数
    每个对象消亡前自动调用析构函数,在对象结束生命周期前做善后工作,如释放资源

    使用 delete 时、数组元素、局部对象消亡时也会调用析构函数,

    class String{
    	char *p;
    	public:
    		complex(size_t size){ p = new char[size]; }
    		~ complex(){ delete [] p; }	
    }
    

    构造函数与析构函数调用示例

    在这里插入图片描述


    封闭类

    成员变量中有类对象时,该类称为封闭类(enclosing)

    对于封闭类,默认构造函数不可用,因为没有说明成员对象如何构造
    因此必须使用有初始化列表说明成员对象如何构造的构造函数

    封闭类的构造函数调用时,成员对象按照类的声明顺序
    按照初始化列表调用相应的构造函数,或者使用默认构造函数 依次构造

    封闭类的析构函数调用后,会依次调用成员对象的析构函数,次序与构造函数相反
    在这里插入图片描述
    当使用封闭类的默认复制构造函数时,其默认实现使用复制构造函数初始化成员对象
    在这里插入图片描述
    当然,如果自定义复制构造函数,可以使用初始化列表指定成员对象的构造方式


    2020/1/17

  • 相关阅读:
    汽车加油问题--贪心算法
    区间相交问题---贪心算法
    算法-动态规划-数字三角问题
    jar转成exe
    kafka zookeeper学习(2) 测试kafka与zookeeper环境
    kafka zookeeper学习(1) windows搭建kafka与zookeeper环境
    java调用linux系统命令
    linux hg(mercurial)入门
    redis集群构建过程 linux windows
    Java JTextArea不能实时刷新的问题
  • 原文地址:https://www.cnblogs.com/kafm/p/12721785.html
Copyright © 2011-2022 走看看