簡體   English   中英

C++:沒有匹配的 function 用於調用:為什么需要一個空的構造函數?

[英]C++: no matching function for call: why is an empty constructor needed?

當我嘗試編譯以下代碼時:

class a {

  int i;

  public :
  a(int);
};

class b {
  a mya;  
  int j;

  public:
  b(int);

};

a::a(int i2) {
  i=i2;
}

b::b(int i2) {
  mya=a(i2); 
  j=2*i2;
}

int main() {

}

我收到以下錯誤:

prog.cpp:21:12: error: no matching function for call to ‘a::a()

 b::b(int i2) {
            ^
prog.cpp:17:1: note: candidate: ‘a::a(int)

 a::a(int i2) {
 ^
prog.cpp:17:1: note:   candidate expects 1 argument, 0 provided
prog.cpp:1:7: note: candidate: ‘constexpr a::a(const a&)’
 class a {
       ^
prog.cpp:1:7: note:   candidate expects 1 argument, 0 provided
prog.cpp:1:7: note: candidate: ‘constexpr a::a(a&&)

prog.cpp:1:7: note:   candidate expects 1 argument, 0 provided

似乎需要一個沒有 class a 參數的構造函數。 我不明白為什么,我唯一一次創建 a 類型的 object 時,我調用了以 int 作為參數的構造函數。

我知道解決方案是添加一個沒有 arguments 的構造函數。 但為什么?

謝謝你的回答,最好的問候,

傑羅姆

b的構造函數中, mya=a(i2); 是賦值(但不是初始化)。 在進入構造函數的主體之前,嘗試默認初始化myaa沒有默認構造函數。

正如您所說,您可以為a添加一個默認構造函數,然后mya將被默認初始化,然后在b的構造函數中分配。

更好的方法是在成員初始化列表中初始化mya

b::b(int i2) : mya(i2) {
//           ^^^^^^^^^
  j=2*i2; // this could be moved to member initializer list too
}

(以下所有 ISO 標准參考參考N4659:2017 年 3 月 Kona 后工作草案/C++17 DIS


根據[class.base.init]/9 ,類型為abmya成員是默認初始化的,但a沒有定義默認構造函數:

非委托構造函數中,如果給定的潛在構造子對象不是由 mem-initializer-id 指定的(包括由於構造函數沒有 ctor-initializer而沒有 mem-initializer-list的情況),

  • (9.1)如果實體具有默認成員初始值設定項的非靜態數據成員 [...],則實體從 [dcl.init] 中指定的默認成員初始值設定項進行初始化
  • (9.2) 否則,如果實體是匿名聯合或變體成員([class.union.anon]),則不執行初始化;
  • (9.3) 否則,實體被默認初始化。

在這里,由於mya沒有與默認成員初始化程序一起聲明, 因此 [class.base.init]/9.3適用。

[class.base.init]/9的示例甚至涵蓋了這種特殊情況:

[...] [ 例子:

 struct A { A(); }; struct B { B(int); }; struct C { C() { } // initializes members as follows: A a; // OK: calls A::A() const B b; // error: B has no default constructor int i; // OK: i has indeterminate value int j = 5; // OK: j has the value 5 };

—結束示例]

您可以通過為mya提供默認成員初始化程序來解決它,例如[class.base.init]/9.1適用

class b {
  a mya{42};  // default member initializer
  int j;

  public:
  b(int);
};

或者,在b的構造函數的定義中使用成員初始化列表; b::b(int) ,這樣[class.base.init]/7適用:

mem-initializer 中的表達式列表或花括號初始化列表用於根據 [dcl.init] 的初始化規則初始化指定的子對象(或者,在委托構造函數的情況下,完整的 class 對象)直接初始化。 [ 例子:

 struct B1 { B1(int); /*... */ }; struct B2 { B2(int); /*... */ }; struct D: B1, B2 { D(int); B1 b; const int c; }; D::D(int a): B2(a+1), B1(a+2), c(a+3), b(a+4) { /*... */ } D d(10);

—結束示例] [...]

從而直接初始化mya成員:

b::b(int i2) : mya(i2) {
           //  ^^^^^^^- member initializer list
  j=2*i2;
}

暫無
暫無

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

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