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

  • 相关阅读:
    二分图 洛谷P2055 [ZJOI2009]假期的宿舍
    并查集 洛谷P1640 [SCOI2010]连续攻击游戏
    贪心 洛谷P2870 Best Cow Line, Gold
    贪心 NOIP2013 积木大赛
    快速幂 NOIP2013 转圈游戏
    倍增LCA NOIP2013 货车运输
    树形DP 洛谷P2014 选课
    KMP UVA1328 Period
    动态规划入门 BZOJ 1270 雷涛的小猫
    KMP POJ 2752Seek the Name, Seek the Fame
  • 原文地址:https://www.cnblogs.com/long98/p/10352250.html
Copyright © 2011-2022 走看看