Ändern von self innerhalb der const-Methode über einen nicht const-Zeiger auf self
Frage
Im folgenden Beispiel const
Das Objekt kann sich über ändern const
Methode, weil es in dieser Methode über auf sich selbst zugreift non-const
Zeiger.(Gleiches Programm auf ideone)
#include <iostream>
struct Object;
Object * g_pObject;
struct Object
{
Object():m_a(0){}
void ModifySelfViaConstMethod() const
{
g_pObject->m_a = 37;
}
int m_a;
};
int main()
{
Object o;
g_pObject = &o;
const Object & co = o;
std::cout << co.m_a << "\n";
co.ModifySelfViaConstMethod();
std::cout << co.m_a << "\n";
return 0;
}
Ich bin nicht so gut darin, den C++-Standard zu lesen, also frage ich hier:
Was sagt der Standard dazu?
A)const
Die Methode garantiert Ihnen nicht, dass Ihr Objekt unverändert bleibt, wenn Sie solche Dinge tun
b) Ist das klar definiert und muss es kompiliert werden?
c) andere?
Lösung
Was sagt der Standard dazu?
Das heißt es (paraphrasierend). this
Typ hat const Object *
, sodass Sie Member nicht direkt ändern oder nicht konstante Memberfunktionen über aufrufen können this
.Es sagt nichts darüber aus, was Sie mit globalen Variablen tun können, auf die die Funktion möglicherweise Zugriff hat.Es steuert nur den direkten Zugriff auf das Objekt, für das die Funktion aufgerufen wird.
const
Die Methode garantiert Ihnen nicht, dass Ihr Objekt unverändert bleibt, wenn Sie solche Dinge tun
Nein, tut es nicht.Es gibt die Absicht an, dass die Funktion das Objekt nicht ändern wird, und bietet einen gewissen Schutz vor einem versehentlichen Verstoß gegen diese Absicht.Es hindert einen entsprechend geistesgestörten Programmierer nicht daran, es zu verwenden const_cast
, oder (wie hier) unkontrollierte Kopplung über globale Variablen, um das Versprechen zu brechen.
Ist das klar definiert und muss es kompiliert werden?
Ja. o
ist selbst nicht konstant, daher hindert Sie nichts daran, einen nicht konstanten Zeiger oder Verweis darauf zu verwenden.Der const
Die Memberfunktion schränkt den Zugriff auf das Objekt nur über ein this
, nicht auf beliebige Objekte über andere Zeiger.
Andere Tipps
Wenn Sie a const
Funktion, es ist „zu Ihrem eigenen Besten“.
Mit anderen Worten: Sie erklären es const
denn gemäß Ihrem ursprünglichen Entwurf soll es kein Objekt ändern, mit dem es während der Laufzeit aufgerufen wird.
Wenn Sie zu einem späteren Zeitpunkt in der Implementierung dieser Funktion das Objekt ändern, wird der Compiler Sie „anschreien“ und Ihnen sagen, dass es falsch ist.
Natürlich kann der Compiler einen solchen Versuch nur dann erkennen, wenn er angewendet wird this
.
Im gegebenen Beispiel kann der Compiler das Problem nicht identifizieren, da ein Vergleich zwischen diesen erforderlich ist this
Und g_pObject
, und ein solcher Vergleich kann nur zur Laufzeit stattfinden.
Wenn eine Methode als deklariert wird const
, stellt der Compiler sicher, dass die Instanz, auf die der zeigt this
Der Zeiger wird nicht geändert.Wenn Sie versuchen, die zu ändern this
Beispielsweise schlägt der Compiler fehl.Der Compiler hat jedoch keine Möglichkeit, dies zu wissen g_pObject
Und this
zeigen tatsächlich auf dieselbe Instanz.Das erfordert einen Laufzeitvergleich, und kein Compiler wird Zeit damit verschwenden, Laufzeitvergleiche aller innerhalb von a verwendeten Zeiger durchzuführen const
Methode in dem unwahrscheinlichen Fall, dass sie könnte verbinde die this
Zeiger.Wenn Sie also eine ändern möchten Object
Über einen externen Zeiger müssen Sie Ihre eigene Prüfung durchführen, z. B.:
void ModifySelfViaConstMethod() const
{
if (g_pObject != this)
g_pObject->m_a = 37;
}
Konstanz ist in C++ ein Sicherheitsinstrument, keine Sicherheit.
Der Code, in dem die Konstanz berücksichtigt wird, wird höchstwahrscheinlich wie erwartet funktionieren, und alle unbeabsichtigten Versuche, die Konstanz aufzugeben, werden vom Compiler gewarnt.
In Fällen, in denen „ich weiß, was ich tue“, findet man die ganze Vielfalt an Werkzeugen von const_cast
Betreiber und mutable
Schlüsselwort zur banalen C-Stilbesetzung.