2016-08-24 90 views
47

是否使具有多個參數explicit的構造函數具有任何(有用)效果?使用多個參數的顯式構造函數

例子:

class A { 
    public: 
     explicit A(int b, int c); // does explicit have any (useful) effect? 
}; 
+0

那麼,如果它只有一個參數,它會阻止隱式類型轉換,但在這種情況下,除非第二個參數被設置爲默認值,否則我看不到任何有用的效果。 – Ziezi

+8

它用於大括號初始化。 – 101010

+0

@ 101010你能詳細說明一下嗎? – Ziezi

回答

62

直到C++ 11,是的,沒有理由對使用explicit一個多參數的構造函數。

由於初始值設定項列表的原因,在C++ 11中發生了變化。基本上,初始化器列表的複製初始化(但不直接初始化)要求構造器不被標記爲explicit

實施例:

struct Foo { Foo(int, int); }; 
struct Bar { explicit Bar(int, int); }; 

Foo f1(1, 1); // ok 
Foo f2 {1, 1}; // ok 
Foo f3 = {1, 1}; // ok 

Bar b1(1, 1); // ok 
Bar b2 {1, 1}; // ok 
Bar b3 = {1, 1}; // NOT OKAY 
+1

即使@Story Teller第一次提出了支持初始化,因爲明確的(雙關語意)提到C++ 11,我接受了這個答案。 –

+3

@PeterG。如果兩個答案都相同,首先回答應該很重要。 Sheftel's是更好的恕我直言。 :) – StoryTeller

19

你會在它絆倒捆帶初始化(例如在陣列)

struct A { 
     explicit A(int b, int c) {} 
}; 

struct B { 
     B(int b, int c) {} 
}; 

int main() { 
    B b[] = {{1,2}, {3,5}}; // OK 

    A a1[] = {A{1,2}, A{3,4}}; // OK 

    A a2[] = {{1,2}, {3,4}}; // Error 

    return 0; 
} 
14

通過@StoryTeller和@Sneftel優異的答案是主要原因。然而,恕我直言,這是有道理的(至少我這樣做),作爲未來證明的一部分後來更改代碼。考慮你的例子:

class A { 
    public: 
     explicit A(int b, int c); 
}; 

此代碼不直接受益於explicit

一段時間後,你決定爲c添加一個默認值,所以就變成這樣:

class A { 
    public: 
     A(int b, int c=0); 
}; 

做這件事時,你就c參數聚焦 - 回想起來,它應該有一個默認值。您不一定關注A本身是否應該隱式構建。不幸的是,這一變化使explicit再次相關。

因此,爲了傳達一個ctor爲explicit,在首次編寫該方法時可能會付出代價。

+3

偉大的軟件工程方面:) – StoryTeller

+1

@StoryTeller非常感謝!順便問一下你的答案,順便說一句。 –

+0

但是當維護者添加默認值並且得出結論**應該作爲轉換構造函數可用時,情況如何呢?現在,他們必須**刪除那些永遠存在的「顯式」,並且技術支持將被關於該改變的呼叫淹沒,並花費**小時**解釋「顯式」只是噪聲,並且將其清除是無害。就我個人而言,我並不擅長預測未來。很難決定界面應該看起來像**現在**。 –