2017-05-05 68 views
2
#include <iostream> 

using namespace std; 

class Test{ 
private: 
    Test(int a, int b=0) 
    { 
     cout << "private constructor\n"; 
    } 
public: 
    Test(int a) 
    { 
     cout << "public constructor\n"; 
    } 
}; 

int main() 
{ 
    Test t(1); 
} 

候選人當我試圖編譯代碼gcc說:編譯器提供私人構造爲程序代碼中

test.cpp: In function ‘int main()’: 
test.cpp:20:10: error: call of overloaded ‘Test(int)’ is ambiguous 
    Test t(1); 
     ^
test.cpp:12:2: note: candidate: Test::Test(int) 
    Test(int a) 
^
test.cpp:7:2: note: candidate: Test::Test(int, int) 
    Test(int a, int b=0) 
^
test.cpp:5:7: note: candidate: Test::Test(const Test&) 
class Test{ 
    ^

clang說:

test.cpp:20:7: error: call to constructor of 'Test' is ambiguous 
     Test t(1); 
      ^~ 
test.cpp:7:2: note: candidate constructor 
     Test(int a, int b=0) 
     ^
test.cpp:12:2: note: candidate constructor 
     Test(int a) 
     ^
test.cpp:5:7: note: candidate is the implicit copy constructor 
class Test{ 
    ^
1 error generated. 

是什麼的原因歧義?由於Test(int,int)是私人的,因此不應該在Test t(1)中調用它。一個可能的答案是(我最初想的),它使得兩個相同的構造函數簽名成爲可能,即Test()只能在私有構造函數中調用一個int。但在程序代碼Test t(1)只適用於公共構造函數,所以它不應該提供私有構造函數作爲候選。爲什麼這麼說?

+1

同樣的原因,因爲這:http://stackoverflow.com/questions/39042240/why-is-a-public-const-method-not-被稱爲什麼時候非const-one-is-private/39042574#39042574 – NathanOliver

回答

4

這是不明確的一個明確的理由,因爲根據標準:

[class.access/5]

應當指出的是,訪問成員和 控制基類,而不是他們的知名度。成員的名稱仍然是 可見的,並且當基類不可訪問時,基類的隱式轉換仍然考慮爲 。建立給定結構的解釋不考慮訪問控制。如果所建立的解釋使用 不可訪問的成員名稱或基類,則該結構爲 不合格。

而且能見度意味着,編譯器必須考慮建設兩個重載,他們是爲你傳遞的參數同樣良好。

由於構造函數是私有的,因此只能通過類及其成員的作用域訪問,只需刪除默認參數值即可。您可以通過其他方式在您的類定義中保留此默認值。例如,通過在類實現文件中引入一個常數:

int const default_b = 0; 

// ... 

return Test{a, default_b}; 
+0

單線程細化到答案:名稱解析發生在檢查訪問權限之前。 +1。 –