Frage

Kann jemand erklären, warum folgender code nicht kompiliert?Mindestens auf g++ 4.2.4.

Und mehr interessant, warum wird es kompilieren, wenn ich Darsteller zu int?

#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;
}
War es hilfreich?

Lösung

Sie müssen tatsächlich das statische Element definieren irgendwo (nach der Klassendefinition). Versuchen Sie folgendes:

class Foo { /* ... */ };

const int Foo::MEMBER;

int main() { /* ... */ }

Das sollte die Beseitigung der undefinierten Referenz erhalten.

Andere Tipps

Das Problem kommt wegen eines interessanten Kampf der neuen C ++ Funktionen und was Sie versuchen zu tun. Zuerst schauen wir uns die push_back Unterschrift einen Blick:

void push_back(const T&)

Es wird erwartet, eine Referenz auf ein Objekt vom Typ T. Unter dem alten System der Initialisierung, ein solches Element vorhanden ist. Zum Beispiel der folgende Code kompiliert nur in Ordnung:

#include <vector>

class Foo {
public:
    static const int MEMBER;
};

const int Foo::MEMBER = 1; 

int main(){
    std::vector<int> v;
    v.push_back( Foo::MEMBER );       // undefined reference to `Foo::MEMBER'
    v.push_back( (int) Foo::MEMBER ); // OK  
    return 0;
}

Das ist, weil es ein tatsächliches Objekt irgendwo ist, die diesen Wert darin gespeichert hat. Wenn Sie jedoch auf das neue Verfahren zum Spezifizieren static const Mitglieder wechseln, wie Sie oben haben, ist Foo::MEMBER nicht mehr ein Objekt. Es ist eine Konstante, etwas ähnlich:

#define MEMBER 1

Aber ohne die Kopfschmerzen eines Präprozessormakro (und mit Typ-Sicherheit). Das bedeutet, dass der Vektor, der eine Referenz erwartet, nicht bekommen kann.

Der C++ - standard erfordert eine definition für die statische const-Mitglied, wenn die definition ist irgendwie notwendig.

Die definition ist notwendig, für Beispiel, wenn die Adresse verwendet wird. push_back nimmt den parameter durch const Referenz, und so streng muss der compiler die Adresse des Mitglieds und müssen Sie definieren, es in den Namensraum.

Wenn Sie explizit cast die Konstante, die Sie erstellen eine temporäre und es ist diese temporäre, die gebunden ist, um die Referenz (unter besonderen Regeln in der Norm).

Dies ist ein wirklich interessanter Fall, und ich denke tatsächlich, dass es sich lohnt, dass ein Thema so, dass der std geändert, um das gleiche Verhalten für Ihre ständige Mitglied zu werden!

Obwohl, in einer seltsamen Art und Weise dies könnte man als eine legitime Verwendung des unären ' + ' - operator.Im Grunde das Ergebnis der unary + ist ein rvalue und so die Regeln für die Bindung von rvalues const Referenzen gelten, und wir don ' T verwenden Sie die Adresse unserer statische const-member:

v.push_back( +Foo::MEMBER );

Aaa.h

class Aaa {

protected:

    static Aaa *defaultAaa;

};

Aaa.cpp

// You must define an actual variable in your program for the static members of the classes

static Aaa *Aaa::defaultAaa;

Keine Ahnung, warum die Gussarbeiten, aber Foo :: Mitglied ist erst das erste Mal zugewiesen Foo geladen wird, und da Sie es nie geladen, wird es nie zugeordnet. Wenn Sie einen Verweis auf ein Foo irgendwo hätte, wäre es wahrscheinlich funktionieren.

In Bezug auf die zweite Frage: push_ref nimmt Bezug als Parameter, und Sie können nicht einen Verweis auf static const memeber 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 gut.

oder zumindest mein Kollege, der dies so sagt aufgelöst.

Mit C ++ 11, würden die oben möglich sein, Grundtypen wie

class Foo {
public:  
  static constexpr int MEMBER = 1;  
};

Der constexpr Teil erzeugt eine statische Ausdruck im Gegensatz zu einer statischen Variable - und das verhält sich wie eine extrem einfache Inline-Methode Definition. Der Ansatz erwies sich als ein bisschen wackelig mit C-String constexprs innerhalb Template-Klassen, though.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top