Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » statischer Pointer

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
23.07.2008, 22:19 Uhr
Lensflare



Hallo

ich bekomme bei folgendem Code einen Linker Error, den ich überhaupt nicht verstehe:


C++:
class Test
{
private:
  static Test* _staticThis;

public:
  static void f(Test* p) { _staticThis = p; }
};

int main()
{
    Test* test = new Test();
    Test::f(test);
    return 0;
}



Der Fehler:

bei Dev-Cpp:

Code:

[Linker error] undefined reference to `Test::_staticThis'



bei MSVC 2005:

Code:
Error    1    error LNK2019: unresolved external symbol "private: static class Test * Test::_staticThis" (?_staticThis@Test@@0PAV1@A) referenced in function "public: static void __cdecl Test::f(class Test *)" (?f@Test@@SAXPAV1@@Z)    main.obj


--
Wenn das Gehirn so einfach wäre, dass wir es verstehen könnten, wären wir so einfach, dass wir es nicht verstehen könnten.
(Emerson Pugh Trost)

Dieser Post wurde am 23.07.2008 um 22:22 Uhr von Lensflare editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
23.07.2008, 22:54 Uhr
0xdeadbeef
Gott
(Operator)


_staticThis ist nur deklariert, nicht definiert. Du musst nach der Klasse noch

C++:
Test *Test::_staticThis;


einfügen. Der Hintergrund ist, dass die Deklaration typischerweise in einem Header auftaucht, die Variable selbst aber nur in einer Übersetzungseinheit existieren darf - sonst käme der Linker durcheinander. Das sähe dann so aus:

C++:
// Test.hh

class Test {
private:
  static Test* _staticThis; // Deklaration

public:
  static void f(Test* p);
};



C++:
// Test.cc
#include "Test.hh"

Test *Test::_staticThis; // Instanziierung

void Test::f(Test *p) {
   _staticThis = p;
}



C++:
// main.cc
#include "Test.hh"

int main() {
    Test* test = new Test();
    Test::f(test);
    return 0;
}


--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 23.07.2008 um 22:54 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
23.07.2008, 23:36 Uhr
Lensflare



Ok danke schon mal. So funktioniert es.

Ich verstehe das Problem leider immer noch nicht.
Wieso wird das nicht implizit gemacht?
Wieso muss das bei nicht-statischen Variablen nicht gemacht werden?
--
Wenn das Gehirn so einfach wäre, dass wir es verstehen könnten, wären wir so einfach, dass wir es nicht verstehen könnten.
(Emerson Pugh Trost)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
24.07.2008, 00:15 Uhr
0xdeadbeef
Gott
(Operator)


Es kann nicht impliziert gemacht werden, weil sonst in jeder Übersetzungseinheit, in der der Header eingebunden wird, eine eigene statische Variable vorhanden wäre, und der Linker nicht wüsste, welche davon er jetzt benutzen soll.

Bei nicht-statischen Variablen ist das unproblematisch, weil diese bei der Objekterstellung erzeugt werden. Statische Variablen darf es nur einmal geben.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
24.07.2008, 03:40 Uhr
Lensflare




Zitat:
Es kann nicht impliziert gemacht werden, weil sonst in jeder Übersetzungseinheit, in der der Header eingebunden wird, eine eigene statische Variable vorhanden wäre, und der Linker nicht wüsste, welche davon er jetzt benutzen soll.


Müsste das nicht durch die Präprozessor Direktiven verhindert werden?

C++:
#ifndef BLA_H
#define BLA_H

//...

#endif



Die statische Variable ist ja in der Klasse und solange die Klasse nicht doppelt existiert, dürfte doch auch die statische Variable nicht doppelt exisieren.
--
Wenn das Gehirn so einfach wäre, dass wir es verstehen könnten, wären wir so einfach, dass wir es nicht verstehen könnten.
(Emerson Pugh Trost)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
24.07.2008, 04:32 Uhr
0xdeadbeef
Gott
(Operator)


Die hatte ich zwar oben in meinem Beispiel vergessen, aber einen Unterschied macht es für die statische Variable nicht. Die Include-Guards werden für jede Übersetzungseinheit neu ausgewertet - sonst hättest du ja auch die Klassendeklaration nur in einer.

Das Problem ist das selbe wie bei allen globalen Variablen. Sie kann nicht in mehreren Übersetzungseinheiten instanziiert werden, sonst kriegst du in dem Moment, in dem sie zusammengelinkt werden sollen, das Problem, dass der Linker nicht weiß, welche er benutzen soll.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
25.07.2008, 10:21 Uhr
stephanw
localhorst


Außerdem kann der Compiler nicht wissen, mit welchem Wert diese statische Variable initialisiert werden soll. Dies kann man bei der Definition nämlich mit angeben, aber nicht bei der Deklaration im Header.

Zitat von 0xdeadbeef:


C++:
// Test.cc
#include "Test.hh"

Test *Test::_staticThis = 0; // Null - Zeiger

void Test::f(Test *p) {
   _staticThis = p;
}





Int-Variablen könntest Du mit jedem passenden Wert belegen. Für Objekte den geeigneten Konstruktoraufruf dorthin schreiben, und und und.
--
Reden ist Schweigen und Silber ist Gold.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
25.07.2008, 11:21 Uhr
Kest
saint



Zitat von stephanw:
Außerdem kann der Compiler nicht wissen, mit welchem Wert diese statische Variable initialisiert werden soll.

Das stimmt doch nicht, oder?
Ein statisches Klassenelement ohne Konstruktor wird zu 0 initialisiert.
--
Wenn man einen Hufschlag hört, sollte man >Pferd< denken und nicht >Zebra<.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
25.07.2008, 12:48 Uhr
stephanw
localhorst


Ja, das mag sein. Ich schreib es dennoch lieber hin. Und eigentlich wollte ich damit auch nur ausdrücken, dass es sinnvoll ist, wenn ich (wie 0xdeadbeef schrieb) eben diese Definition irgendwo vornehmen MUSS, weil ich dann dort eben auch einen bestimmten Wert verwenden KANN.
--
Reden ist Schweigen und Silber ist Gold.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: