Problem mit struct
-
Wieso erzeugt mein Compiler hier Warnungen?
#include <iostream> #include "test_struktur. using namespace std; int main() { obj.test = "abc"; cout << obj.test << endl; return 0; }struct my_struct { std::string test; }; my_struct obj;[BCC32 Warnung] xlocinfo(53): W8058 Präcompilierter Header: Initialisierte Daten im Header kann nicht erzeugt werden
[ILINK32 Warnung] Warning: Public Symbol '_obj' ist in Modul C:\DOKUMENTE UND EINSTELLUNGEN\User\DESKTOP\Struktur\DEBUG\Struktur.OBJ und C:\DOKUMENTE UND EINSTELLUNGEN\User\DESKTOP\Struktur\DEBUG\Struktur.OBJ definiert
Bei einer Klasse kann ich das ja so machen das keine Warnungen kommen:
#include <iostream> #include "test_struktur.h" using namespace std; int main() { obj.test = "abc"; cout << obj.test << endl; return 0; }class my_class {public: std::string test; }; my_class obj; extern my_class obj;Btw. ist das eigentlich ok so mit dem extern?
Wenn ich im struct das extern verwende dann kommt:
[ILINK32 Fehler] Error: Nicht aufl÷sbares externes '_obj'
-
1. Der Compiler hat immer recht.
2. Der Compiler hat immer recht.
3. Der Compiler hat immer recht.
4. Der Compiler hat immer recht.
5. Der Compiler hat immer recht.
...
99. Du sollst die Grundlagen über Deklaration und Definition lernen.
...
999. Du sollst keine Definitionen in Headerdateien vornehmen.
...
...
-
Das Problem ist, dass Du eine globale Instanz im Header definierst. Der Compiler generiert dann eine Instanz der Klasse und exportiert das globale Symbol "obj". Soweit ist das in Ordnung. Wenn Du die Headerdatei in einer anderen Sourcedatei includierst, dann wird der Compiler das gleiche machen, wenn er die andere Sourcedatei übersetzt. Der Linker will dann die 2 vom Compiler generierten Objektdateien Linken und findet aber 2 mal das globale Symbol "obj". Das mag der Linker nicht.
Objektdefinitionen gehören daher immer in die Sourcedatei. Im Header dürfen nur Deklarationen auftauchen.
Zur Verdeutlichung:
my_class obj;ist eine Definition. Da sage ich dem Compiler: bitte lege das Objekt an und rufe seinen Konstruktor auf. Das Schlüsselwort extern macht daraus eine Deklaration:
extern my_class obj;sagt dem Compiler: "es existiert ein globales Objekt mit dem Namen "obj". Der Compiler kann es verwenden und verlässt sich darauf, dass der Linker das Objekt dann nachher findet.
Du verwendest offensichtlich den Microsoft Compiler. Der verwendet hier offensichtlich präcompilierte Header und dieser Mechanismus geht davon aus, dass die Regel auch eingehalten wird.
-
Wutz schrieb:
999. Du sollst keine Definitionen in Headerdateien vornehmen.
Es sei denn Klassendefinitionen. In allen Geschmacksrichtungen (d.h. auch enums und unions, wenns denn unbedingt unions sein müssen). Ach ja, und Templatedefintionen. Und Definitionen von inline-Funktionen (sei es jetzt freistehend oder implizit als Methoden in Klassendefinitionen).
Ach, und vielleicht statische Konstanten...