2017-02-16 7 views
3

Ich habe 2 Konstruktoren in Struktur 'Matrix'.Struct Konstruktor Aufruf ist mehrdeutig

matrix(const unsigned int m, const unsigned int n); 
matrix(const std::vector<std::vector<double>> &elements); 

Als ich es wie folgt nennen

matrix mat({{1},{1}}); 

Es wirft Fehler

call of overloaded ‘matrix(<brace-enclosed initializer list>)’ is ambiguous 
note: candidate: matrix::matrix(const std::vector<std::vector<double> >&) 
note: candidate: matrix::matrix(const matrix&) 

Also, denkt es, dass {{1}, {1}} - ist 'Matrix' Objekt, aber wie?

+0

@AnT, ja, weil ich Vektor der Vektoren habe. Ich kann sogar {{1,2,3}, {1,2}, {1}} eingeben und es wird kompiliert. –

+0

@AnT, ja, mein Fehler, danke. –

+0

'{1}' ist ein 'Vektor ', '{{1}, {1}}' ist 'std :: vector >'. Wenn Sie den ersten Konstruktor entfernen, sollte der Code trotzdem kompiliert werden. –

Antwort

4

Also, denkt es, dass {{1}, {1}} - ist 'Matrix' Objekt, aber wie?

In Ihrem Beispielcode

matrix mat({{1},{1}}); 

Sie ausdrücklich gesagt die Compiler zu versuchen, und dass die Expression zu einem matrix Konstruktor zu entsprechen.

Es "denkt" nicht den Ausdruck {{1},{1}} ist eine Matrix, es versucht, es in eins zu machen, weil Sie es gebeten haben.

Was, warum Sie den Fehler (was nicht, was Sie ist gefragt, aber scheint erwähnenswert), dann ist es, weil

vector<double> v{1}; 

eine gültige Erklärung eines Vektors mit einem einzigen Wert (1.0), und so

vector<vector<double>> vv{{1},{1}}; 

ist auch eine gültige Erklärung eines Vektors enthält zwei Elementvektoren, die jeweils mit einem einzigen double Element Wert 1,0, und so schließlich

mat{{{1},{1}}}; 

wäre ein gültige Übereinstimmung für den Vektorkonstruktor. Da diese Umwandlung implizit erlaubt ist, sind wir

mat m({{1},{1}}); 

als

mat m(mat{{{1},{1}}}); 

und damit die Mehrdeutigkeit zu umschreiben erlaubt. Beachten Sie die runden und geschweiften Klammern sorgfältig.

können Sie entweder der Konstruktor implizit machen, oder einfach nur zu einheitlicher Initialisierung Stil gewöhnen und

mat m{{{1},{1}}}; 

an erster Stelle schreiben.

+0

Aber warum versucht es diese ({{1}, {1}}) Konstruktion in eine 'Matrix' umzuwandeln? Funktioniert das so? Davor habe ich nur Unterricht genommen und bin nie damit konfrontiert worden. –

+0

Du hast es gesagt! Jede Anweisung wie 'mat m (EXPRESSION);' als würde der Compiler aufgefordert, eine neue 'mat' aus' EXPRESSION' zu erstellen. Das ist sowohl für Strukturen als auch für Klassen identisch, und nichts davon wird sich ändern, wenn Sie Ihre Struktur in eine Klasse verwandeln (stellen Sie einfach sicher, dass alles öffentlich ist). – Useless

+0

@Useless: Sie sollten erwähnen, dass '{{1}, {1}}' den ersten Konstruktor findet - das ist der Grund für die Mehrdeutigkeit! –

3

matrix mat({{1},{1}}) Wenn der Compiler Aufruf findet diese beiden mehrdeutigen Konstruktionspfade:

  • aufrufen vector<vector>> Konstruktor durch Konstruieren zwei Vektoren mit einer Elementen in einem Vektor.

  • Erstellen Sie implizit eine temporäre Matrix mit dem ersten Konstruktor und konstruieren Sie dann mat mit diesem temporären.

    1. Erstellen Sie eine temporäre Matrix von matrix(const unsigned int m, const unsigned int n). (Der erste {1} zu m abgestimmt ist, wird die zweite {1} zu n abgestimmt.)

    2. Try mat von dem temporären zu konstruieren von matrix(const matrix&) verwenden.

den ersten (oder beides) Konstruktor (s) als explicit unzweideutig die matrix mat({{1},{1}}) aufrufen machen Marking ...

matrix(const std::vector<std::vector<double>> &elements); 

... ein.

wandbox example

+0

'Erzeugen Sie implizit eine temporäre Matrix mit dem ersten Konstruktor', dh {{m}, {n}} wird zu m, n? –

+1

@VladMarkushin: Es ist klar aus der Ausgabe hier: http://melpon.org/wandbox/permlink/6qfAZ5Y7It0k5OJE - grundsätzlich ja. –

+1

@VladMarkushin: Ich habe meine Antwort aktualisiert - ist es jetzt klar? –