[英]Why doesn't my compiler recognise “Bond() = default;”?
請看這個代碼
class Bond
{
public:
Bond(int payments_per_year, int period_lengths_in_months);
Bond() = default;
private:
const int payments_per_year;
const int period_length_in_months;
};
int main()
{
Bond b; // Error here
}
在嘗試編譯時,我收到一個錯誤:
錯誤C2280:'Bond :: Bond(void)':嘗試引用已刪除的函數“。
因為我已經添加了默認構造函數,所以這不是“3規則”違規。
為什么編譯器不識別Bond() = default;
?
由於存在需要顯式初始化的常量成員,因此將禁止使用默認構造函數。
因此,由於該抑制,書寫Bond() = default
不重新引入默認的構造函數。
(您可以通過刪除類中的所有構造函數來查看此效果 - 您仍然無法實例化b
。)
如果你從成員中刪除const
,那么一切都會好的; 雖然另一種選擇是為每個const
成員提供一個支撐或等於初始化器 ;
const int payments_per_year = 2;
const int period_length_in_months = 6;
例如。
您受到C ++標准草案(或C ++ 11中的[class.ctor] p5 )的[class.default.ctor] p2部分的影響,該部分說:
如果出現以下情況,則將類X的默認默認構造函數定義為已刪除:
...
- 任何const-qualified類型(或其數組)的非變量非靜態數據成員,沒有brace-or-equal-initializer,沒有用戶提供的默認構造函數,
...
他們可能解決問題的關鍵是使用沒有大括號或等號初始化程序的短語,所以如果你提供的大括號或者等於初始化程序將解決你的問題,例如:
const int payments_per_year{12};
const int period_length_in_months{48};
brace-or-equal-initializer不需要大括號,我們可以看到這個語法:
brace-or-equal-initializer:
= initializer-clause
braced-init-list
但是使用統一初始化有一些優點,例如縮小轉換格式不正確 ,值得習慣使用它們。
gcc和clang都為此提供了更有意義的診斷, 請參閱實時godbolt會話 。 有時在多個編譯器上嘗試代碼會很有幫助,特別是如果你有一個像這樣的最小測試用例,例如clang說:
warning: explicitly defaulted default constructor is implicitly deleted [-Wdefaulted-function-deleted]
Bond() = default;
^
note: default constructor of 'Bond' is implicitly deleted because field 'payments_per_year' of const-qualified type 'const int' would not be initialized
const int payments_per_year;
^
...
另一個修復方法是在常量聲明中指定一個默認值:
const int payments_per_year = {12};
這仍然可以被值構造函數覆蓋,但允許默認構造函數繼續。
這也是一種非常靈活的簡化多個構造函數的方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.