簡體   English   中英

我不明白這個例子中什么時候調用了構造函數

[英]I don't understand when the constructor is called in this example

您好我一直在嘗試分析以下使用操作重載的代碼。

#include <iostream>
using namespace std;

#define DBG(str) cout << str << endl

class Integer {
    int n;
public:
    Integer(int _n) : n(_n) { DBG("A"); };
    Integer(const Integer& i) : n(i.n) { DBG("B"); };

    Integer& operator=(const Integer& i) { DBG("C"); n = i.n; return *this; };
    Integer& operator+=(const Integer& i) { DBG("D"); n += i.n; return *this; };

    friend Integer operator+(const Integer& a, const Integer& b);
    friend Integer operator*(const Integer& a, const Integer& b);
    friend ostream& operator<<(ostream& os, const Integer& i);

};

Integer operator+(const Integer& a, const Integer& b) {
    DBG("E"); return Integer(a.n + b.n);
}
Integer operator*(const Integer& a, const Integer& b) {
    DBG("F"); return Integer(a.n * b.n);
}
ostream& operator<<(ostream& os, const Integer& i) {
    DBG("G"); os << i.n; return os;
}

int main() {
    Integer n1(1), n2(2);
    Integer n = 5 + n1 + 2 * n2;

    cout << n << endl;
}

結果是......

A // constructor called when n1 is created
A // constructor called when n2 is created
A // when is this called?
A // when is this called?
F // called when 2 * n2 is operated
A // called when Integer(a.n * b.n) is created in the multiplication function
E // called when 5 + n1 is operated
A // called when Integer(a.n + b.n) is created in the addition function
E // called when (5 + n1) + (2 * n2) is operated
A // called when Integer is created in the addition function
G // called when n is printed using cout
5 // value of n

現在我最麻煩的是 A 的第三和第四個打印。在句子Integer n = 5 + n1 + 2 * n2; 正在創建 object n 並將正確的值分配給 n,所以應該調用復制構造函數? 我認為應該發生的是應該調用構造函數來制作(5 + n1 + 2 * n2)的臨時object,然后通過將其復制到n,應該調用復制構造函數。 我理解錯了什么?

你能解釋一下發生了什么嗎? 先感謝您。

問題出在這一行:

Integer n = 5 + n1 + 2 * n2;

intInteger沒有operator+ ,但編譯器默默地進行了從intInteger隱式轉換,因為默認情況下,所有單參數構造函數都可以用作轉換方法。 這是您的實時代碼(改進了一點)。

這是 C++ 的危險特性之一,因此在構造函數之前要使用explicit關鍵字。 如果你添加它:

explicit Integer(const Integer& i) : n(i.n) { DBG("B"); };

編譯器將報告錯誤,因為現在無法執行隱式轉換並且沒有operator+(int, const Integer&)operator*(int, const Integer&)

您的operator+operator*函數接收一個const Integer&作為參數。

當計算出這條線 ( 5 + n1 + 2 * n2 ) 5 和 2 將自動轉換為Integer

如果您不希望它們被轉換,您應該考慮為int創建運算符作為參數。

編輯:您也可以使用顯式構造函數。

例如: explicit Integer(int _n){...}

//感謝@foreknownas_463035818 的評論

Friend function is used in operator overloading only when the first parameter of the operator function is not an object of the target class for which the operator function is defined. 在您的情況下, Integer

Integer operator+(const Integer& a, const Integer& b) {
    DBG("E"); return Integer(a.n + b.n);
}
Integer operator*(const Integer& a, const Integer& b) {
    DBG("F"); return Integer(a.n * b.n);
}

,第一個參數確實是 Integer 類型的Integer ,這是您的目標 class。 您可能想要的是能夠將您的Integer object 與原始 integer 類型一起用作操作數。 將您的朋友 function 簽名更改為:

Integer operator+(const int& a, const Integer& b) {
    DBG("E"); return Integer(a + b.n);
}
Integer operator*(const int& a, const Integer& b) {
    DBG("F"); return Integer(a * b.n);
}

請注意,使用a而不是an因為當運算符 function 被定義為友元時,兩個操作數都作為參數傳遞。(與第一個操作數是調用對象的非友元運算符函數不同)。 所以a包含一個int類型的值,而不是一個Integer類型的值。

對包含DBG("A")的構造函數的匿名調用是在將 5 和 2 從int轉換為Integer時發生的隱式轉換的結果。

盡管您的代碼可能有效,但這是不可靠的。 希望這可以幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM