c++ - 繼承建構子 - 析構函數




該類有多少個構造函數? (5)

我正在為即將進行的C ++考試做準備,並且遇到了有關類和構造函數的問題:

Fraction類有多少個構造函數?”

class Fraction {
//...
public:
   Fraction(int numerator = 0, int denominator = 1);
//...
};

我以為只有一個,但是他們建議有三個:

Fraction();
Fraction(n);
Fraction(n, d);

換句話說:
具有默認值的函數是否是重載函數?


具有默認值的函數是否是重載函數?

不,過載看起來像

Fraction();
Fraction(int numerator);
Fraction(int numerator, int denominator);

並且每個都有自己的實現(定義),而帶有默認參數的函數只有一個實現。

我以為只有一個,但他們建議有3個:...

“ Fraction類有多少個構造函數?”

這是一個技巧性的問題,旨在欺騙您顯示 單個構造函數 聲明的可用調用變體。

給定代碼段的 肯定 答案是 3 (即 3 )。

有一個專門的構造函數(提供三種調用方式),如果您不 delete 它們或提供自定義實現,則編譯器會自動生成一個副本並移動該構造函數:

Fraction(int numerator = 0, int denominator = 1); // (1)
// Redundant, just for demonstration:
Fraction(const Fraction& rhs) = default; // (2)
Fraction(Fraction&& rhs) = default; // (3)

所以對於這樣的考試,如果你會回答

該類具有一個構造函數

反正那是錯的。 如果你會回答

該類具有三個構造函數 (如您所寫的那樣,這是可接受的答案)

您需要深入解釋,為什麼要這麼做(如上所述)。
在任何口試中,我都會要求您準確備份原因,因此我會在學徒考試中進行備份。


因為這取決於您傳遞的參數:

Fraction() --> Fraction(0,1)
Fraction(n)---> Fraction(n,1)
Fraction(n,m)

因此,它提供了3個構造函數。 這裡沒有過載。


您可以使用上述類中聲明的單個構造函數以三種不同的方式創建Fraction對象。 構造函數具有默認參數。 如果您不傳遞任何參數,它將採用該參數的相應值。

  1. Fraction a; //分子為0,分母為1

  2. Fraction a(10); //分子為10,分母為1

  3. Fraction a(10, 20); //分子為10,分母為20


您問題的答案與以下三個後續問題有關:

  1. 在C ++ 11,C ++ 11或C ++ 14及更高版本之前?
  2. 隱式定義的構造函數是否有用?
  3. 成員是什麼? 不可複製成員的存在將刪除隱式副本構造函數。

顯式定義只是一個構造函數。 不管該調用是否顯式提供0、1或2個參數,編譯器都會插入一個三參數調用。

'11之前的版本中沒有移動構造函數,'11之前有兩個隱式構造函數定義, Fraction(const Fraction &) noexceptFraction(Fraction &&) noexcept ,檢查可訪問的 cppreference ,在'14中,何時存在隱式定義的move構造函數更改。

不幸的是,您遇到的問題是看起來很單純,但是技術性很強。 我希望您的班級不要堅持過度簡化C ++,這是學習它的最糟糕的方法。


這種函數定義定義了一個函數,但定義了兩種附加的調用語法。 當採用函數指針或將模板函數參數與重載函數匹配時,細微的差別變得顯而易見:在這種情況下,您只有具有完整參數列表的函數作為可用的重載類型。

現在棘手的事情是,我們在這裡談論的是構造函數,而構造函數不會像普通函數那樣進行相同類型的重載解析,並且就所有目的而言,除了語法上都是不可訪問的。 特別是,此定義 確實 作為默認構造函數單獨計算。 它也從int單獨計為轉換構造函數,可用作((Fraction)3)。

因此,出於所有實際目的,它在構造函數類別中創建了三個不同的 語法 實體。 與普通函數相反,沒有函數上下文可以使重載解析揭示三個實際函數簽名與三個僅語法調用約定之間的差異。

對於筆試來說,這不是一個好問題。 對於口試,這確實是一件很重要的事情,因為涉及到許多微妙之處,因此形式正確答案(如果有)和形式錯誤答案之間的差異不太可能與實際知識和技能以及任何答案背後的原因相關比答案本身更重要。





constructor