2017-05-05 30 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。 –