C++ 各種構造函數的調用方式

c++的類中有5種值得注意的基本的函數:

  • 無參構造函數
  • 有參構造函數
  • 拷貝構造函數
  • 賦值函數
  • 析構函數

關於析構函數,需要注意的點在上一篇博客裏面 c++: 是否會自動delete? 也提到過了,在這裏暫時不多說。這篇博客主要記錄這3個構造函數、1個賦值函數的調用方式,希望大家學習之後,不但知道如何調用,還可以根據一句話來判斷到底調用了幾次構造函數。

可以通過一個例子來說明,假如我現在有一個Animal類,其中爲了調試,我特意在每個構造函數中加入了輸出語句,來看看調用的結果:

struct Animal {
    int age;
    string name;

    Animal() {  // 無參構造函數
        cout << "No-args Constructor" << endl;
        age = -1;
        name = "Unknown";
    }

    Animal(string name, int age) { // 有參構造函數
        cout << "Argumenting Constructor" << endl;
        this->name = name;
        this->age = age;
    }

    Animal(const Animal &other) { // 拷貝構造函數
        cout << "Copy constructor" << endl;
        this->name = other.name;
        this->age = other.age;
    }

    Animal& operator=(const Animal &other) { // 賦值函數
        cout << "Assigning" << endl;
        this->name = other.name;
        this->age = other.age;
    }

    ~Animal() {
        cout << "Destructor" << endl;
    }

    friend ostream& operator<<(ostream &out, const Animal &animal) {
        out << "Animal[" << animal.name << "]: " << "age=" << animal.age;
        return out;
    }
};

然後,以下代碼會演示創建一個實例的多種方式,並且我把每一種創建方式的輸出結果、以及一些思考,以註釋的方式寫出來:

int main() {


    //-----------------無參構造函數-----------------------

    Animal animal01; // 雖然不是很明顯,但是這裏不是使用指針,而是直接操作實例,所以這裏實際上調用了無參構造函數。
    cout << animal01 << endl;
    /*
      輸出:
        No-args Constructor
        Animal[Unknown]: age=-1
    */


    Animal animal02(); // 這並不能調用無參構造函數!編譯器會當作是某個函數的聲明,所以下面輸出的1也許是函數的地址(暫時沒有深究)。
    cout << animal02 << endl;
    /*
      輸出:
        1
    */


    Animal animal03 = Animal();
    // 注意,這裏可能有人會認爲:等號右邊調用了默認構造函數,然後因爲賦值給左邊所以又調用了一次拷貝構造函數,就會認爲這樣子會白白浪費掉一個實例。
    // 實際上,根據輸出可以看到,結果並不是上述那樣,而是這個語句整體上只調用了一次無參構造函數。即與“Animal animal03;”效果一樣。
    cout << animal03 << endl;
    /*
      輸出:
        No-args Constructor
        Animal[Unknown]: age=-1
    */

    //----------------------------------------------


    //-----------------有參構造函數-----------------------  

    Animal animal001("Lion", 1);
    cout << animal001 << endl;
    /*
      輸出:
        Argumenting Constructor
        Animal[Lion]: age=1
    */


    Animal animal002 = Animal("Lion", 1);
    // 這裏同上面所說的,整體上僅僅調用了一次有參構造函數。
    cout << animal002 << endl;
    /*
      輸出:
        Argumenting Constructor
        Animal[Lion]: age=1
    */

    //----------------------------------------------


    //----------------拷貝構造函數-------------------  

    Animal animal0001 = animal001;
    // 這裏要區分“拷貝構造函數”和“賦值函數”的調用時機。前者是聲明和賦值在同一行,後者不是。所以這裏屬於拷貝構造函數。
    cout << animal0001 << endl;
    /*
      輸出:
        Copy constructor
        Animal[Lion]: age=1
    */  

    //-------------------------------------------


    //------------------賦值函數------------------------  

    Animal animal;
    animal = animal0001;
    // 因爲這裏animal的聲明和賦值不在同一行,所以編譯器會認爲不是拷貝構造,而是一般的賦值語句。
    cout << animal << endl;
    /*
      輸出:
        No-args Constructor
        Assigning
        Animal[Lion]: age=1
    */  

    //-----------------------------------

    return 0;
}
--------------------- 

轉自: https://blog.csdn.net/vitalemon__/article/details/60869721

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章