2017-09-29 76 views
6

mam klasęDomyślnie argumentem pozwalając konstruktor zadzwonić Metoda prywatna

class A 
{ 
public: 
    class Key 
    { 
     Key() {} 
     Key(Key const &) {} 
    }; 

    A(Key key, int a = 5) {} 
}; 

Konstruktor Key jest prywatny, więc nikt nie powinien być w stanie zbudować obiekt A. Jednak z następującego kodu:

int main() { 
    A a(A::Key()); // this compiles !!! 
    A a2(A::Key(), 5); // this doesn't 
    // somehow defaulting the argument causes the private constructor 
    // to be OK - no idea why 
    return 0; 
} 

poprzez wykorzystanie standardowego argumentu dla int a w moim konstruktora, kompilator szczęśliwie kompiluje mój wykorzystanie A::Key() pomimo faktu, że jest prywatny. Jeśli jednak jawnie podam wartość dla a, kompilator poprawnie rozpoznaje, że próbuję użyć prywatnego konstruktora i błędy. Dlaczego to? Czy jest jakiś sposób, aby zmusić kompilator do błędu również w pierwszym przykładzie?

Zobacz przykład na żywo z przykładu here.

Odpowiedz

7

Dzieje się tak z powodu najbardziej irytującej analizy.

A a(A::Key()); 

nie tworzy A nazwie a i zbudować go z tymczasowym A::Key. Tworzy on funkcję a, która zwraca wartość A i pobiera wskaźnik bez nazwy do funkcji, która zwraca wartość A::Key.

Jeśli dodać parę nawiasów do niego dostaniesz błąd kompilatora

A a((A::Key())); 

że próbujesz zadzwonić prywatny konstruktor. Alternatywnie można użyć mundurowych inicjalizacji który również disambiguate ją i spowoduje błąd kompilacji

A a(A::Key{}); 
+1

Wiedziałem, widziałem to gdzieś wcześniej ... Jeden z tych rzeczy, które napotkasz raz na 5 lat i jestem flummoxed przez ponieważ Nie widziałem tego od tak dawna ... Dzięki za pomoc. –

+1

@R_Kapp Nie ma problemu, miło mi pomóc. – NathanOliver