zoukankan      html  css  js  c++  java
  • C++构造函数简单用法

    个人笔记,仅供复习

    1.构造函数

    1.1 基本概念:

    • 每个类都有构造函数,如果自己不写,编译器会生成一个默认的无参数构造函数。
    • 构造函数名字与类名相同,可以有参数,不可以有返回值(void也不可以)。
    • 构造函数的作用是对对象进行初始化,如给变量赋初值。

    1.2 注意:

    • 如果定义了构造函数,则编译器不生成默认的无参数构造函数。
    • 对象生成时构造函数自动被调用。对象一旦生成,就再也不能在其上执行构造函数。
    • 一个类可以有多个构造函数(函数重载)。
    • 对象生成调用的可能是构造函数或复制构造函数。

    1.3 构造函数的意义:

            构造函数执行必要的初始化工作,有了构造函数就不必再写初始化函数,也不用担心对象没有初始化。

    1.4 代码实例:

    #include<iostream>
    #include<string>
    using namespace std;
    class Myclass{
    	private :
    		int int_a;
    		string str;
    	public :
    		Myclass(int x = 0,string y = "123"){
    			int_a = x;
    			str = y;
    		}
    		void print(){
    			cout << int_a << " " << str << endl;
    		}
    };
    int main()
    {
    	Myclass mc(1,"456");
    	mc.print();
    	return 0;
    }

    1.5 可以有多个构造函数,参数个数或类型不同(函数重载):

        1.5.1 冒号语法在构造函数中用法:  用在构造函数后表示:初始化列表 

         构造函数初始化时必须采用初始化列表一共有三种情况: 

    1. 需要初始化的数据成员是成员对象
    2. 需要初始化const 修饰的类成员
    3. 需要初始化引用成员数据
    #include<iostream>
    #include<string>
    using namespace std;
    class Myclass{
    	private :
    		int int_a;
    		string str;
    	public :
    		Myclass(int x,string y):int_a(x),str(y) {}//1
    		Myclass(int x):int_a(x) {}//2
    		Myclass(string y):str(y) {}//3
    		void print(){
    			cout << int_a << " " << str << endl;
    		}
    };
    int main()
    {
    	Myclass mc(1,"456");//调用1
    	Myclass mc2(5);//调用2 
    	Myclass mc3("abc");//调用3 
    	return 0;
    }

    1.6 构造函数参数可以是类本身:

    #include<iostream>
    #include<string>
    using namespace std;
    class Complex {
    	private :
    		double real, imag;
    	public:
    		Complex(double r, double i );
    		Complex (double r );
    		Complex (Complex c1, Complex c2);
    };
    Complex::Complex(double r, double i) {
    real = r; imag = i;
    }
    
    Complex::Complex(double r){
    	real = r; imag = 0;
    }
    Complex::Complex (Complex c1, Complex c2){
    	real = c1.real+c2.real;
    	imag = c1.imag+c2.imag;
    }
    
    int main()
    {
    	Complex c1(3) , c2 (1,0), c3(c1,c2);// c1 = {3, 0}, c2 = {1, 0}, c3 = {4, 0};
    	return 0;
    }

    1.7 构造函数在数组中的使用:

            每生成一个类,就调用一次构造函数。生成数组类的时候,可以用 { } 对对应的类调用构造函数。

    #include<iostream>
    using namespace std;
    class Test {
    	public:
    		Test( int n) { } //(1)
    		Test( int n, int m) { } //(2)
    		Test() { } //(3)
    };
    int main()
    {
    	Test array1[3] = { 1, Test(1,2) };
    	// 三个元素分别用(1),(2),(3)初始化
    	Test array2[3] = { Test(2,3), Test(1,2) , 1};
    	// 三个元素分别用(2),(2),(1)初始化
    	Test * pArray[3] = { new Test(4), new Test(1,2) };
    	//两个元素分别用(1),(2) 初始化
    	return 0;
    } 
    

    2.复制构造函数

    2.1 基本概念:

    • 只有一个参数,即对同类对象的引用
    • 形如X::X( X& )X::X( const X &),二者选一,后者能以常量对象作为参数
    • 如果没有定义复制构造函数,那么编译器生成默认复制构造函数。默认的复制构造函数完成复制功能

    注:

    • 不允许有形如 X::X( X )的构造函数
    • 如果定义了自己的复制构造函数,那默认复制构造函数将不存在

    2.2 复制构造函数起作用的三种情况:

    • 用一个对象去初始化同类的另一个对象
    	Complex c2(c1);
    	Complex c2 = c1;//初始化语句,非赋值语句。 
    • 如果某函数有一个参数是类A的对象,那么该函数被调用时,类A的复制构造函数将被调用
    #include<iostream>
    #include<string>
    using namespace std;
    class A
    {
    	public:
    		A() { };
    		A( A & a) {
    			cout << "Copy constructor called" <<endl;
    		}
    };
    void Func(A a1){ }
    int main(){
    	A a2;
    	Func(a2);
    	return 0;
    }
    程序输出结果为: Copy constructor called

    • 如果函数的返回值是类A的对象时,则函数返回时,A的复制构造函数被调用
    #include<iostream>
    #include<string>
    using namespace std;
    class A
    {
    	 public:
    		 int v;
    		 A(int n) { v = n; };
    		 A( const A & a) {
    			 v = a.v;
    			 cout << "Copy constructor called" <<endl;
    		 }
    };
    A Func() {
    	A b(4);
    	return b;
    }
    int main() {
    	cout << Func().v << endl; 
    	return 0;
    }

    输出结果:Copy constructor called

                        4

    有些编译器会对上述代码进行优化(如dev),那么就只会输出4。

    注:对象之间赋值并不导致复制构造函数被调用

    2.3 常量引用参数的使用:

    void Fun(Myclass obj_){
    	cout << "fun" <<endl;
    }
    这样的函数,调用时生成形参会引发复制构造函数开销比较大可以使用Myclass & 引用类型作为形参。如果希望实参的值不会被改变,可以加上const关键字。

    3.析构函数

    3.1 什么是析构函数:名字与类名相同,在前面加‘~’,没有参数和返回值,一个类最多只能有一个析构函数。

    3.2 特点:

    • 名字与类名相同,在前面加‘~’, 没有参数和返回值,一 个类最多只能有一个析构函数。 
    • 析构函数对象消亡时即自动被调用。可以定义析构函数来在对象消亡前做善后工作,比如释放分配的空间等。 
    • 如果定义类时没写析构函数,则编译器生成缺省析构函数。 缺省析构函数什么也不做。 
    • 如果定义了析构函数,则编译器不生成缺省析构函数。 

    3.3 代码实例:

    #include<iostream>
    using namespace std;
    class A
    {
    	 public:
    		 ~A(){
    		 	cout << "now" <<endl;
    		 } 
    };
    void Fun(){
    	A a;
    }
    int main() {
    	Fun();
    	return 0;
    }

    当函数调用结束时,局部对象a被释放,析构函数被调用。每当一个对象消亡,就必定会调用析构函数。

    3.4 析构函数和数组:对象数组生命期结束时,对象数组的每个元素的析构函数都会被调用。

    3.5 析构函数和delete运算符:

    • delete导致析构函数被调用
    • 若new一个对象数组,那么用delete释放时应写[]。否则只delete一个对象(调用一次析构函数)
    Ctest  * pTest;
    pTest = new Ctest;  //构造函数调用 
    delete pTest;          //析构函数调用 
    pTest = new Ctest[3]; //构造函数调用3次 
    delete [] pTest;           //析构函数调用3次 

    4.类型转换构造函数

    4.1 基本概念:

    • 定义转换构造函数的目的是实现类型的自动转换
    • 只有一个参数,而且不是复制构造函数的构造函数,一般就可以看作是类型转换构造函数
    • 当需要的时候,编译系统会自动调用类型转换构造函数,建立一个无名的临时对象(或临时变量)

    4.2 代码实例:

    #include<iostream>
    using namespace std;
    class A{
    	public:
    		int first;
    		double second;
    		A(int a){
    			this->first = a;
    			this->second = 0.5;
    		}
    };
    int main()
    {
    	A a = 4;//调用了类型转换构造函数 
    	a = 5;//调用了类型转换构造函数 
    	cout << a.first << " " << a.second << endl;
    	return 0;
    }

  • 相关阅读:
    HDU 3949 XOR
    [JXOI2018]游戏
    树状数组 Binary Indexed Tree/Fenwick Tree
    Java 多线程编程
    概率算法
    最长回文子串 Manacher算法
    动态规划-最长上升子序列 LIS
    流水作业调度
    多机调度问题
    A*搜索算法
  • 原文地址:https://www.cnblogs.com/long98/p/10352250.html
Copyright © 2011-2022 走看看