Ich habe ein wenig Mühe, genau herauszufinden, wie const in einem bestimmten Fall gilt. Hier ist der Code, den ich habe:
%Vor%Grundsätzlich habe ich eine Klasse namens test. Es verwendet intern vier Widgets, und ich brauche es, um diese zurückzugeben, aber wenn Test const deklariert wurde, möchte ich, dass die Widgets auch const zurückgegeben werden.
Kann mir jemand erklären, warum der Code in main () kompiliert?
Vielen Dank.
Dies wird kompiliert, da obwohl der WidgetHolder ein const-Objekt ist, diese Const-Ness nicht automatisch auf Objekte angewendet wird, auf die der WidgetHolder verweist. Stellen Sie sich das auf einer Maschinenebene vor - wenn das WidgetHolder-Objekt selbst im schreibgeschützten Speicher gehalten würde, könnten Sie immer noch in Dinge schreiben, auf die der WidgetHolder zeigte.
Das Problem scheint in dieser Zeile zu liegen:
%Vor%Wie Frank bereits erwähnt hat, werden Ihre Referenzen in der WidgetHolder-Klasse nach der Rückkehr des Konstruktors ungültige Referenzen enthalten. Daher sollten Sie dies ändern zu:
%Vor%Nachdem Sie das getan haben, wird es nicht kompilieren, und ich überlasse es als eine Übung für den Leser, um den Rest der Lösung zu erarbeiten.
Sie müssen einen neuen Typ speziell für das Halten von const Widget & amp; Objekte. Dh:
%Vor%Sie erhalten nun den folgenden Fehler (in gcc 4.3):
%Vor%Ein ähnliches Idiom wird in der Standardbibliothek mit Iteratoren verwendet, dh:
%Vor%unveränderbar.AccessWidgets ():
An diesem Punkt erstellen Sie ein neues Objekt vom Typ WidgetHolder. Dieses Objekt ist nicht durch const geschützt.
Sie erstellen auch neue Widgets im WidgetHolder und keine Verweise auf das Wdiget.
Ihr WidgetHolder
enthält ungültige Referenzen (Zeiger). Sie übergeben Objekte auf dem Stapel an den Konstruktor und halten dann Verweise auf ihre (temporären) Adressen. Dies ist garantiert zu brechen.
Sie sollten Referenzen nur auf Objekte mit der gleichen (oder längeren) Lebensdauer wie die Referenz selbst zuweisen.
Übergeben Sie Referenzen an den Konstruktor, wenn Sie Referenzen halten müssen. Noch besser, halte die Referenzen nicht und mache nur die Kopien.
EDIT: Er hat seine Antwort gelöscht, was mich ein wenig albern aussehen ließ:)
Die Antwort von Flame ist gefährlich falsch. Sein WidgetHolder nimmt Bezug auf ein Wertobjekt im Konstruktor. Sobald der Konstruktor zurückkehrt, wird das übergebene Wertobjekt zerstört und Sie erhalten einen Verweis auf ein zerstörtes Objekt.
Eine sehr einfache Beispiel-App mit seinem Code zeigt dies deutlich:
%Vor%Die Ausgabe wäre etwas wie
%Vor%Um dies zu vermeiden, sollte der WidgetHolder -Konstruktor Verweise auf die Variablen enthalten, die als Referenzen gespeichert werden sollen.
%Vor%Die ursprüngliche Abfrage war, wie WidgetHolder als const zurückgegeben wird, wenn die enthaltene Klasse const ist. C ++ verwendet const als Teil der Funktionssignatur und daher können Sie const und none const Versionen der gleichen Funktion haben. Die none const one wird aufgerufen, wenn die Instanz keine Konstante ist, und die Konstante const wird aufgerufen, wenn die Instanz const ist. Daher besteht eine Lösung darin, auf die Widgets im Widget-Halter anhand von Funktionen und nicht direkt zuzugreifen. Ich habe ein einfacheres Beispiel erstellt, von dem ich glaube, dass es die ursprüngliche Frage beantwortet.
%Vor%In Bezug auf den ursprünglichen Code denke ich, dass es einfacher wäre, einen WidgetHolder als Mitglied der Klasse Test zu haben und dann entweder einen const- oder keinen const-Verweis darauf zurückzugeben und die Widgets zu privaten Mitgliedern des Halters zu machen, und stellen Sie für jedes Widget einen const und keinen const Accessor bereit.
%Vor%Und dann auf die Hauptklasse
%Vor%