2015-05-05 2 views
8

diesen Satz von Objekten und Aussagen zu haben:Verständnis nicht C++ Typenkonflikt: const Foo * Foo * const &

QSet<Foo*> set; 
iterator QSet::insert(const T & value) //type of the function I want to call 
const Foo * get() const     //type of the function I use to get the argument 

set.insert(get());      //the line showing up as error 

ich den Fehler „keine bekannte Umwandlung für Argument 1 von 'const Foo *' auf ' Foo * const & ". Ich schätze, ich habe Probleme, diese Typen zu lesen, weil ich keine Ahnung habe, was ich tun soll, damit das funktioniert.

Von dem, was ich gelesen habe, gilt das const-Schlüsselwort für den Typ auf seiner linken Seite mit Ausnahme einer obersten Ebene const, die auf der linken Seite des Typs geschrieben werden kann, für den es gilt. Meine Vermutung wäre, dass ich get() zu einer Referenz konvertieren muss, aber ich bin mir nicht sicher, wie ich das machen soll.

+0

Dies ist nicht "top-level' const' ". 'get()' gibt einen Zeiger auf "const Foo" zurück, nicht auf einen "const" -Zeiger. – Barry

+0

Also mein Verständnis, dass ein "const" am Anfang für alles zu seiner Rechten gilt, war falsch? Was genau gilt für ein solches "const"? –

Antwort

7

Es scheint hier ein paar Missverständnisse zu geben (sowohl vom Fragesteller als auch von einigen Antworten).

Zuerst, Sie sagten "Meine Vermutung wäre, dass ich get() zu einer Referenz konvertieren muss, aber ich bin mir nicht sicher, wie man das macht". Lassen Sie uns versuchen, dies zu klären:

1) "Ich muss get() zu einer Referenz konvertieren" - Eigentlich nicht!

iterator QSet::insert(const T & value) nimmt in der Tat eine Referenz. Aber es ist ein Hinweis auf den Typ T. Die Frage ist also: "Was ist der Typ T"?

In diesem Fall T=Foo *. So insert, in diesem Fall der Vorlage, ist eigentlich:

iterator QSet::insert(Foo * const & value) - von rechts nach links gelesen werden: insert nimmt einen Verweis auf einen konstanten Zeiger auf ein Foo.

2) "Ich bin nicht sicher, wie man das macht [einen Zeiger auf eine Referenz konvertieren]" - während Sie dies hier nicht tun müssen, tun Sie dies im Allgemeinen, indem Sie das Ergebnis von get aufheben . Zum Beispiel: *(get()).

Sekunde, der Compilerfehler.Der Fehler tritt auf, weil es einen Konflikt gibt:

a) get() gibt einen const Foo *

b) aber set speichert eine Foo* - KEINE const Foo *, so insert akzeptiert nur ein veränderbarer Foo

So können Sie Speichern Sie keinen konstanten Zeiger in Ihrem . Dies ist sinnvoll, da Sie set verwenden können, um auf die darin enthaltenen Foo zuzugreifen und diese zu ändern, was Sie mit einer const Foo nicht zu tun versprechen.

Dieser Hinweis sollte hilfreich sein:

https://isocpp.org/wiki/faq/const-correctness

Sie auch denken können, ob Sie nur eine QSet<Foo> anstelle eines QSet<Foo*> verwenden können. Im ersten Fall werden sich die Dinge wahrscheinlich so verhalten, wie Sie es erwarten.

+1

Betrachtet man https://isocpp.org/wiki/faq/const-correctness#const-ref-alt, stimmt es, dass 'const X *' für beliebig komplexe Konstrukte 'X' gleich' X const * 'ist ? –

+0

Es ist, wenn 'X' ein Typ ist - es ist nicht, wenn' X' komplizierter ist. In der Tat musste ich deshalb genau diesen Tausch machen, bevor ich 'T' einsetzte. Wenn man es 'X const *' schreibt, ist es einfacher, von rechts nach links zu lesen ("ein Zeiger auf eine Konstante" X "). Aber wenn man es const X * schreibt, wird es im Quellcode deutlicher, dass der Typ" a Konstante 'X'". So normalerweise sehen Sie es 'const X *' in Code. – Corey

+0

Für Vorlagen könnte es verwirrend sein, also ... Wer 'QSet schrieb, könnte coded' insert (const T & value) 'oder' insert (T const & value) 'und sie wären gleich gewesen, aber das liegt daran, dass der Compiler weiß, was zu tun ist. Wenn ** du ** T auf Papier oder in deinem Kopf ersetzen willst, du ** Muss man sich das vorstellen als 'insert (T const & value) ' – Corey

5

Sie versuchen, ein const Foo * zu nehmen und es in eine QSet<Foo *> einfügen, aber der Compiler wird nicht automatisch ein const Foo * zu einem einfachen Foo *, um so zu tun, konvertieren.

+1

@ Jeffrey: Weil das 'QSet ' nicht-const Zeiger enthält. Sie können einen Zeiger auf const nicht implizit in einen Zeiger auf Nonconst ändern. –

3

Ich löste das Problem, indem ich den Typ des Sets wie folgt änderte.

QSet<Foo const*> set; 

Mit dieser Änderung ist die Kompilierung erfolgreich.

3

Sie verletzen die Const-Ness des von Ihrer get()-Funktion zurückgegebenen Zeigers. get() gibt einen Zeiger auf ein const-Objekt vom Typ Foo zurück, aber Sie versuchen dann, es in einen Vektor von nicht-const Foo Zeigern einzufügen. Sie müssen const_cast den Rückgabewert von get() oder ändern Sie den Rückgabetyp get() von const Foo* zu nur Foo*.

+0

Das wären die anderen beiden Alternativen gewesen. –