構造函數,複製構造函數,賦值運算符重載函數

0、People是一個類;

        People p1(1, 2); //調用構造函數
        People p2(2, 4); //調用構造函數

1、 People p = 4; //會調用構造函數,假設構造函數的原型是:People(int a, int b = 1);

#include <iostream>

using namespace std;

class People{
public:
    People(int a, int b = 1){
        num = double(a)/b;
        cout << "構造函數" << endl;
    }

private:
    double num;
};


int main()
{
    People p1(1, 2);
    People p2(2, 4);
    People p = 4;  //會調用構造函數,假設構造函數的原型是:People(int a, int b = 1);

    return 0;
}

注意People p = 4;此時相當於:People p(4);調用構造函數
之所以強調這一點是因爲:People p = p1此時相當於People p(p1);調用複製構造函數

2、 People p = p1 + 4; //會調用重載的加號運算符:People operator + (double number);再因爲返回的是臨時對象而調用構造函數

#include <iostream>

using namespace std;

class People{
public:
    People(int a, int b = 1){
        num = double(a)/b;
        cout << "構造函數" << endl;
    }
    People operator + (double number){
        cout << "operator + (double number) " << endl;
        return People(num + number, 1);//調用構造函數;
    }

private:
    double num;
};


int main()
{
    People p1(1, 2);
    People p2(2, 4);
    People p = p1 + 4;//會調用重載的加號運算符:People operator + (double number);然後調用構造函數
    return 0;
}

3、People p = p1 + 4; //會先調用operator double() { return double(num); },再調用構造函數;

#include <iostream>

using namespace std;

class People{
public:
    People(int a, int b = 1){
        num = double(a)/b;
        cout << "構造函數" << endl;
    }

    People operator + (People & people){//形參如果不使用引用就會調用一次構造函數;
        cout << "重載的+運算符" << endl;
        return People(num + people.num, 1);//調用一次構造函數

    }
    People operator = (double number){
        cout << "重載的operator = (double number) " << endl;
        return People(num + number, 1);//調用構造函數;
    }

    operator double(){
        cout << "調用operator double()" << endl;
        return num;
    }

private:
    double num;
};


int main()
{
    People p1(1, 2);
    People p2(2, 4);
    People p = p1 + 4;//會先調用operator double() { return double(num); };再調用構造函數;

    return 0;
}

這個的原理是:先將p1轉化爲double,即調用 operator double();在進行double的加法操作,計算出結果以後即變成了和例1類似的過程,即再調用一次構造函數;

關於這一點和侯捷老師講的視頻有點兒出入,按照侯捷老師的說法,這個例子應該會報ambiguous的錯誤,
因爲People p = p1 + 4;這一句可以將p1轉化爲4(調用 operator double()),然後double相加;
也可以將4轉化爲People類型(此處調用構造函數,此處存在疑問。。。。因爲一個單獨的4會主動的變爲People嗎?),然後兩個People相加(此處調用People operator + (People & people));

更正::---------------------------------------------------------------
紅線處侯捷老師講的是正確的,因爲我的第3個例子People operator + (People & people)形參帶引用,所以纔沒有出現ambiguous的錯誤,如果不帶&的話,就會出現“error: ambiguous overload for ‘operator+’ (operand types are ‘People’ and ‘int’)|”的錯誤.此時將構造函數前面加上explicit關鍵字還會報錯,因爲加上explicit關鍵字以後,整數4便不會往People類進行轉化了,或許你會想那可以將p1轉化爲整數double啊,然後double + int = double,注意到這一步還是可以的,但是,再往下就沒辦法走了,因爲構造函數是explicit的,People p = (double)x 約等於 People p(x),explicit關鍵字禁止進行復制(拷貝)構造,詳細見C++ primer,P265.

4、People p = p1 + 4;

#include <iostream>

using namespace std;

class People{
public:
    People(int a, int b = 1){
        num = double(a)/b;
        cout << "構造函數" << endl;
    }

    People operator + (People people){//調用一次構造函數;
        cout << "重載的+運算符" << endl;
        return People(num + people.num, 1);//調用一次構造函數

    }

private:
    double num;
};


int main()
{
    People p1(1, 2);
    People p2(2, 4);
    People p = p1 + 4;

    return 0;
}

整個執行過程:先調用構造函數將整數4轉化爲People類型進行參數的傳遞,然後調用重載的People operator + (People people)(此時更好理解的一種方式是:函數去調用重載的People operator + (People people),由於其形參是People類型,所以纔將整數4強制轉化了爲了People(4)類型,見深入理解 運算符的重載,然後重載加號運算符的重載函數在返回的時候會調用構造函數構造一個臨時對象。
即:構造函數 → 重載的+運算符 → 構造函數

總結:

1、 People p = 4; //會調用構造函數,假設構造函數的原型是:People(int a, int b = 1);
2、 People p = p1 + 4; //會調用重載的加號運算符:People operator + (double number);再因爲返回的是臨時對象而調用構造函數
3、 People p = p1 + 4; //會先調用operator double() { return double(num); },再調用構造函數;
4、 People p = p1 + 4; //構造函數 → 重載的+運算符 → 構造函數

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