2017-07-13 1 views
0

J'essaie de fournir deux constructeurs différents pour une classe C++, y compris un membre std :: vecteur:C++ liste initialiseur ci-joint brace dans le constructeur délégué

class A { 

    public: 

     std::vector<int> p; 

     A (std::vector<int> i) { p = i; } 

     A (int x, int y, int z) : A ({x, y, z}) {} 
}; 

int main() { 

    A a ({1, 2, 3}); 

    A a2 (1, 2, 3); 

    return 0; 
} 

Le premier constructeur fonctionne bien, mais le second jette le erreur suivante:

error: call of overloaded ‘A(<brace-enclosed initializer list>)’ is ambiguous 

Quelle est la différence entre les deux méthodes?

+1

Vous pouvez lire [les notes] (http://coliru.stacked-crooked.com/a/72bc6715d2140911). – LogicStuff

+0

Bien sûr, c'est ambigu. '{x, y, z}' Les deux peuvent créer un 'A' temporaire à partir duquel notre' A' actuel doit être copié/déplacé, ou un 'vecteur' à partir duquel' A' doit être construit. Comment le compilateur est-il supposé choisir? – StoryTeller

+0

Lorsque vous obtenez des erreurs, lisez toujours le message d'erreur * full *. Il peut souvent y avoir des notes d'information qui devraient vous aider à comprendre ce qui se passe. –

Répondre

1

Le problème est dans le second constructeur:

A (int x, int y, int z) : A ({x, y, z}) {} 

Depuis A ({x,y,z}) peut appeler les deux

  • le premier constructeur: la liste d'initialisation {x, y, z} peut être jeté dans un std::vector<int> et correspondant au premier constructeur .

  • le deuxième constructeur lui-même: comme vous pouvez le voir here où le constructeur appelle lui-même:


A::A(int, int, int): 
pushl %ebp 
movl %esp, %ebp 
subl $8, %esp 
// ... 
call A::A(int, int, int) // <--- recursive call 
// ... 

Which is the difference between the two methods?

Le premier constructeur accepte tous les vecteurs d'entiers. Des constructions valides sont, par exemple:

A({1}); A({1, 2}); A({1, 2, 4}); A({1, 2, 3, 4, ...}); ... 

Le deuxième constructeur accepte trois nombres entiers. constructions valides sont:

A({1, 2, 3}); A(1, 2, 3); A{1, 2, 3}; 

Comme vous pouvez le voir l'expression A({1, 2, 3}) est acceptée par les deux constructeurs et il est si ambigu (le compilateur ne peut pas savoir, d'une manière déterministe qui choisir).

+1

Je le vois maintenant. Je ne savais pas que {1,2,3} était valide pour construire trois entiers seuls. Y a-t-il un moyen de spécifier lequel appeler pour briser cette ambiguïté? Ou devrais-je juste utiliser une fonction différente à la place du second constructeur? – derkomai

+1

@derkomai vous pouvez ajouter un constructeur explicite de liste de braced-init: 'A (std :: initializer_list i): p (i) {}' – Ap31

+0

C'est exactement ce que je cherchais! – derkomai