2017-09-29 5 views
6

J'ai la classel'argument par défaut constructeur permettant d'appeler la méthode privée

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

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

Le constructeur de Key est privé, donc personne ne devrait être en mesure de construire un objet A. Cependant, avec le code suivant:

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; 
} 

En utilisant l'argument par défaut pour int a dans mon constructeur, le compilateur compile heureusement mon utilisation de A::Key() en dépit du fait qu'il est privé. Si je donne explicitement une valeur pour a, cependant, le compilateur reconnaît correctement que j'essaie d'utiliser un constructeur privé et des erreurs. Pourquoi est-ce? Y a-t-il un moyen de forcer le compilateur à commettre une erreur pour le premier exemple?

Voir here pour l'exemple en direct.

Répondre

7

Ceci est dû à l'analyse la plus vexante.

A a(A::Key()); 

ne crée pas un nom Aa et la construction avec un A::Key temporaire. Il crée une fonction a qui renvoie un A et prend un pointeur sans nom pour la fonction qui renvoie un A::Key.

Si vous ajoutez une paire de parenthèses à elle vous obtiendrez une erreur du compilateur

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

que vous essayez d'appeler un constructeur privé. Vous pouvez également utiliser l'initialisation qui en uniforme et aussi lever l'ambiguïté provoquera une erreur de compilation

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

Je savais que je l'avais vu ça quelque part ... une de ces choses que je INTRODUISE une fois tous les 5 ans et je suis déconcerté par car Je ne l'ai pas vu depuis si longtemps ... Merci pour l'aide. –

+1

@R_Kapp Pas de problème, heureux de vous aider. – NathanOliver