Was bedeuten const
solche Erklärungen? Das const
verwirrt mich.
class foobar
{
public:
operator int () const;
const char* foo() const;
};
Was bedeuten const
solche Erklärungen? Das const
verwirrt mich.
class foobar
{
public:
operator int () const;
const char* foo() const;
};
Antworten:
Wenn Sie das const
Schlüsselwort zu einer Methode hinzufügen , wird der this
Zeiger im Wesentlichen zu einem Zeiger auf ein const
Objekt, und Sie können daher keine Mitgliedsdaten ändern. (Wenn Sie nicht verwenden mutable
, dazu später mehr).
Das const
Schlüsselwort ist Teil der Funktionssignatur. Dies bedeutet, dass Sie zwei ähnliche Methoden implementieren können, eine, die aufgerufen wird, wenn sich das Objekt befindet const
, und eine, die nicht aufgerufen wird.
#include <iostream>
class MyClass
{
private:
int counter;
public:
void Foo()
{
std::cout << "Foo" << std::endl;
}
void Foo() const
{
std::cout << "Foo const" << std::endl;
}
};
int main()
{
MyClass cc;
const MyClass& ccc = cc;
cc.Foo();
ccc.Foo();
}
Dies wird ausgegeben
Foo
Foo const
In der non-const-Methode können Sie die Instanzmitglieder ändern, was in der const
Version nicht möglich ist. Wenn Sie die Methodendeklaration im obigen Beispiel in den folgenden Code ändern, werden einige Fehler angezeigt.
void Foo()
{
counter++; //this works
std::cout << "Foo" << std::endl;
}
void Foo() const
{
counter++; //this will not compile
std::cout << "Foo const" << std::endl;
}
Dies ist nicht ganz richtig, da Sie ein Mitglied als markieren können mutable
und eine const
Methode es dann ändern kann. Es wird hauptsächlich für interne Zähler und ähnliches verwendet. Die Lösung dafür wäre der folgende Code.
#include <iostream>
class MyClass
{
private:
mutable int counter;
public:
MyClass() : counter(0) {}
void Foo()
{
counter++;
std::cout << "Foo" << std::endl;
}
void Foo() const
{
counter++; // This works because counter is `mutable`
std::cout << "Foo const" << std::endl;
}
int GetInvocations() const
{
return counter;
}
};
int main(void)
{
MyClass cc;
const MyClass& ccc = cc;
cc.Foo();
ccc.Foo();
std::cout << "Foo has been invoked " << ccc.GetInvocations() << " times" << std::endl;
}
was ausgeben würde
Foo
Foo const
Foo has been invoked 2 times
Die Konstante bedeutet, dass die Methode verspricht, keine Mitglieder der Klasse zu verändern. Sie könnten die so markierten Mitglieder des Objekts ausführen, selbst wenn das Objekt selbst markiert wäre const
:
const foobar fb;
fb.foo();
wäre legal.
Siehe Wie viele und welche Verwendungszwecke hat "const" in C ++? für mehr Informationen.
Das const
Qualifikationsmerkmal bedeutet, dass die Methoden für jeden Wert von aufgerufen werden können foobar
. Der Unterschied ergibt sich, wenn Sie eine Nicht-Const-Methode für ein Const-Objekt aufrufen. Überlegen Sie, ob Ihr foobar
Typ die folgende zusätzliche Methodendeklaration hatte:
class foobar {
...
const char* bar();
}
Die Methode bar()
ist nicht konstant und kann nur über nicht konstante Werte aufgerufen werden.
void func1(const foobar& fb1, foobar& fb2) {
const char* v1 = fb1.bar(); // won't compile
const char* v2 = fb2.bar(); // works
}
Die Idee dahinter const
ist jedoch, Methoden zu markieren, die den internen Zustand der Klasse nicht verändern. Dies ist ein leistungsstarkes Konzept, das in C ++ jedoch nicht durchsetzbar ist. Es ist eher ein Versprechen als eine Garantie. Und eine, die oft kaputt und leicht kaputt ist.
foobar& fbNonConst = const_cast<foobar&>(fb1);
const
ist jedoch, Methoden zu markieren, die den internen Zustand der Klasse nicht verändern". Das habe ich wirklich gesucht.
const
?
Diese const bedeuten, dass der Compiler einen Fehler macht, wenn die Methode 'with const' interne Daten ändert.
class A
{
public:
A():member_()
{
}
int hashGetter() const
{
state_ = 1;
return member_;
}
int goodGetter() const
{
return member_;
}
int getter() const
{
//member_ = 2; // error
return member_;
}
int badGetter()
{
return member_;
}
private:
mutable int state_;
int member_;
};
Die Prüfung
int main()
{
const A a1;
a1.badGetter(); // doesn't work
a1.goodGetter(); // works
a1.hashGetter(); // works
A a2;
a2.badGetter(); // works
a2.goodGetter(); // works
a2.hashGetter(); // works
}
Lesen Sie dies für weitere Informationen
const
Mitgliedsfunktionen, in der nicht veränderlich erwähnt wird, ist bestenfalls unvollständig.
Blairs Antwort ist genau richtig.
Beachten Sie jedoch, dass es ein mutable
Qualifikationsmerkmal gibt, das den Datenelementen einer Klasse hinzugefügt werden kann. Jedes so gekennzeichnete Mitglied kann in einer const
Methode geändert werden, ohne den const
Vertrag zu verletzen .
Sie können dies (zum Beispiel) verwenden, wenn sich ein Objekt merken soll, wie oft eine bestimmte Methode aufgerufen wird, ohne die "logische" Konstanz dieser Methode zu beeinflussen.
Bedeutung einer Const-Member-Funktion in C ++ Allgemeines Wissen: Grundlegende Zwischenprogrammierung gibt eine klare Erklärung:
Der Typ dieses Zeigers in einer Nicht-Konstanten-Mitgliedsfunktion einer Klasse X ist X * const. Das heißt, es ist ein konstanter Zeiger auf ein nicht konstantes X (siehe Const-Zeiger und Zeiger auf Const [7, 21]). Da das Objekt, auf das sich dies bezieht, nicht const ist, kann es geändert werden. Der Typ in einer const-Member-Funktion einer Klasse X ist const X * const. Das heißt, es ist ein konstanter Zeiger auf eine Konstante X. Da das Objekt, auf das sich dies bezieht, const ist, kann es nicht geändert werden. Das ist der Unterschied zwischen konstanten und nicht konstanten Elementfunktionen.
Also in deinem Code:
class foobar
{
public:
operator int () const;
const char* foo() const;
};
Sie können es so denken:
class foobar
{
public:
operator int (const foobar * const this) const;
const char* foo(const foobar * const this) const;
};
this
ist nicht const
. Der Grund, warum es nicht geändert werden kann, ist, dass es ein Wert ist.
Wenn Sie const
in der Methodensignatur (wie gesagt const char* foo() const;
:) verwenden, teilen Sie dem Compiler mit, dass der Speicher, auf den durch verwiesen wird, this
mit dieser Methode (die foo
hier angezeigt wird) nicht geändert werden kann .
Ich möchte den folgenden Punkt hinzufügen.
Sie können es auch zu einem const &
und machenconst &&
Damit,
struct s{
void val1() const {
// *this is const here. Hence this function cannot modify any member of *this
}
void val2() const & {
// *this is const& here
}
void val3() const && {
// The object calling this function should be const rvalue only.
}
void val4() && {
// The object calling this function should be rvalue reference only.
}
};
int main(){
s a;
a.val1(); //okay
a.val2(); //okay
// a.val3() not okay, a is not rvalue will be okay if called like
std::move(a).val3(); // okay, move makes it a rvalue
}
Fühlen Sie sich frei, um die Antwort zu verbessern. Ich bin kein Experte
*this
ist immer ein l-Wert, auch wenn die Member-Funktion rvalue-ref-qualifiziert ist und für einen rvalue aufgerufen wird. Beispiel .
Das mit der Funktionsdeklaration verwendete Schlüsselwort const gibt an, dass es sich um eine const-Member-Funktion handelt und die Datenelemente des Objekts nicht geändert werden können .
https://isocpp.org/wiki/faq/const-correctness#const-member-fns
Was ist eine "
const
Mitgliedsfunktion"?Eine Mitgliedsfunktion, die ihr Objekt überprüft (anstatt es zu mutieren).
Eine
const
Mitgliedsfunktion wird durch einconst
Suffix direkt nach der Parameterliste der Mitgliedsfunktion angezeigt . Elementfunktionen mit einemconst
Suffix werden als "konstante Elementfunktionen" oder "Inspektoren" bezeichnet.const
Elementfunktionen ohne Suffix werden als "Nicht-Konstante-Elementfunktionen" oder "Mutatoren" bezeichnet.class Fred { public: void inspect() const; // This member promises NOT to change *this void mutate(); // This member function might change *this }; void userCode(Fred& changeable, const Fred& unchangeable) { changeable.inspect(); // Okay: doesn't change a changeable object changeable.mutate(); // Okay: changes a changeable object unchangeable.inspect(); // Okay: doesn't change an unchangeable object unchangeable.mutate(); // ERROR: attempt to change unchangeable object }
Der Aufrufversuch
unchangeable.mutate()
ist ein Fehler, der beim Kompilieren abgefangen wird. Es gibt keinen Laufzeitspeicherplatz oder Geschwindigkeitsverlust fürconst
und Sie müssen keine Testfälle schreiben, um dies zur Laufzeit zu überprüfen.Die nacheilenden
const
aufinspect()
Elementfunktion sollte die Methode bedeuten , die verwendet wird , nicht das Objekt ändern abstrakt (Client-sichtbar) Zustand. Dies unterscheidet sich geringfügig von der Aussage, dass die Methode die „Rohbits“ der Objektstruktur nicht ändert. C ++ - Compiler dürfen die "bitweise" Interpretation nur verwenden, wenn sie das Aliasing-Problem lösen können, das normalerweise nicht gelöst werden kann (dh es kann ein nicht konstanter Alias vorhanden sein, der den Status des Objekts ändern kann). Eine weitere (wichtige) Erkenntnis aus diesem Aliasing-Problem: Das Zeigen auf ein Objekt mit einem Zeiger auf const garantiert nicht, dass sich das Objekt nicht ändert. es verspricht lediglich, dass sich das Objekt über diesen Zeiger nicht ändert .