Kann jemand erklären, warum der folgende Code nicht kompiliert wird? Zumindest unter g ++ 4.2.4.
Und interessanter, warum wird es kompiliert, wenn ich MEMBER auf int umsetze?
#include <vector>
class Foo {
public:
static const int MEMBER = 1;
};
int main(){
vector<int> v;
v.push_back( Foo::MEMBER ); // undefined reference to `Foo::MEMBER'
v.push_back( (int) Foo::MEMBER ); // OK
return 0;
}
Antworten:
Sie müssen das statische Element tatsächlich irgendwo definieren (nach der Klassendefinition). Versuche dies:
Das sollte die undefinierte Referenz loswerden.
quelle
Das Problem ergibt sich aus einem interessanten Zusammenprall neuer C ++ - Funktionen und dem, was Sie versuchen zu tun. Schauen wir uns zunächst die
push_back
Signatur an:Es wird ein Verweis auf ein Objekt vom Typ erwartet
T
. Nach dem alten Initialisierungssystem existiert ein solches Mitglied. Der folgende Code wird beispielsweise problemlos kompiliert:Dies liegt daran, dass sich irgendwo ein tatsächliches Objekt befindet, in dem dieser Wert gespeichert ist. Wenn Sie jedoch zu der neuen Methode zum Festlegen statischer const-Elemente wechseln, wie oben beschrieben,
Foo::MEMBER
handelt es sich nicht mehr um ein Objekt. Es ist eine Konstante, ähnlich wie:Aber ohne die Kopfschmerzen eines Präprozessor-Makros (und mit Typensicherheit). Das bedeutet, dass der Vektor, der eine Referenz erwartet, keine bekommen kann.
quelle
(int)
Besetzung) in der Übersetzungseinheit mit perfekter Sichtbarkeit der Konstante undFoo::MEMBER
wird nicht mehr verwendet . Dies steht im Gegensatz zum ersten Funktionsaufruf, bei dem eine Referenz herumgereicht und an anderer Stelle ausgewertet wird.void push_back( const T& value );
?const&
's können mit rWerten binden.Der C ++ - Standard erfordert eine Definition für Ihr statisches const-Mitglied, wenn die Definition irgendwie benötigt wird.
Die Definition ist beispielsweise erforderlich, wenn die Adresse verwendet wird.
push_back
Nimmt seinen Parameter als const-Referenz und so benötigt der Compiler unbedingt die Adresse Ihres Mitglieds und Sie müssen sie im Namespace definieren.Wenn Sie die Konstante explizit umwandeln, erstellen Sie eine temporäre Konstante, und diese temporäre Konstante ist an die Referenz gebunden (gemäß speziellen Regeln im Standard).
Dies ist ein wirklich interessanter Fall, und ich denke tatsächlich, dass es sich lohnt, ein Problem anzusprechen, damit der Standard geändert wird, um das gleiche Verhalten für Ihr ständiges Mitglied zu haben!
Obwohl dies auf seltsame Weise als legitime Verwendung des unären '+' - Operators angesehen werden könnte. Grundsätzlich ist das Ergebnis von
unary +
ein r-Wert, daher gelten die Regeln für die Bindung von r-Werten an const-Referenzen, und wir verwenden nicht die Adresse unseres statischen const-Elements:quelle
push_back
aconst &
. Die direkte Verwendung des Mitglieds führte dazu, dass das Mitglied an die Referenz gebunden war, für die eine Adresse erforderlich war. Durch Hinzufügen von+
wird jedoch eine temporäre Datei mit dem Wert des Mitglieds erstellt. Die Referenz wird dann an diese temporäre Adresse gebunden, anstatt dass das Mitglied eine Adresse haben muss.Aaa.h
Aaa.cpp
quelle
Keine Ahnung, warum die Besetzung funktioniert, aber Foo :: MEMBER wird erst beim ersten Laden von Foo zugewiesen. Da Sie es nie laden, wird es nie zugewiesen. Wenn Sie irgendwo einen Verweis auf ein Foo hätten, würde es wahrscheinlich funktionieren.
quelle
Mit C ++ 11 wäre das Obige für Basistypen wie möglich
Der
constexpr
Teil erstellt einen statischen Ausdruck im Gegensatz zu einer statischen Variablen - und das verhält sich wie eine extrem einfache Inline-Methodendefinition. Der Ansatz erwies sich jedoch mit C-String-Kontexten innerhalb von Template-Klassen als etwas wackelig.quelle
In Bezug auf die zweite Frage: push_ref verwendet die Referenz als Parameter, und Sie können keine Referenz auf das statische Konstantenmitglied einer Klasse / Struktur haben. Sobald Sie static_cast aufrufen, wird eine temporäre Variable erstellt. Und ein Verweis auf dieses Objekt kann übergeben werden, alles funktioniert einwandfrei.
Oder zumindest mein Kollege, der das gelöst hat, hat es gesagt.
quelle