Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

17.07.2011, 13:04

#pragma once, aber trotzdem mehrfach definierte Symbole

Hallo zusammen,

ich habe ein Problem mit mehrfach definierten Symbolen. Im folgenden Beispiel nenne ich dabei nur _d3d9. Dabei habe ich den Verdacht, dass #pragma once irgendwie nicht funktioniert. Dabei ist mein C++-Compiler der von VS2010, und da sollte es mit dieser Direktive nun keine Probleme mehr geben.

Um das Problem zu erläutern, müsste ich mal die Projektdateien und darin enthaltene #include-Direktiven und Variablen in Reihenfolge ihres Auftretens auflisten. Ich versuche mal, es übersichtlich zu halten. Meine Erklärung weiter unten macht es vielleicht verständlicher. Zur Not schicke ich einem engagierten Helfe (danke!) via PM auch mein aktuelles Projekt.

Die Header grün, die CPPs blau. Includes und Pragma once fett.
Die angeblich mehrfach definierte Variable in rot (sie dient als Einzelbeispiel - es sind aber noch mehr Symbole vorhanden, die auch alle mehrfach definiert seien). Das #include, was diesen Fehler verursacht, auch rot:

Engine3D.h - #pragma once - Definiert global z.B. _d3d9, die Direct3D-Schnittstelle - #include "List.h", #include "Resource.h", #include "ResourceManager.h"
List.h - #pragma once - Nicht relevante weitere Definitionen
Resource.h - #pragma once - Nicht relevante weitere Definitionen
ResourceManager.h - #pragma once - Nicht relevante weitere Definitionen

Engine3D.cpp - #include "Engine3D.h" - Nicht relevante weitere Definitionen
ResourceManager.cpp - #include "Engine3D.h"


Dieser Fehler tritt z.B. auf, sobald ich in ResourceManager.cpp "#include "Engine3D.h" einfüge:
error LNK2005: "struct IDirect3D9 * Engine3D::_d3d9" (?_d3d9@Engine3D@@3PAUIDirect3D9@@A) ist bereits in ResourceManager.obj definiert.

Aber wie kann das sein? Ich sehe das so:
Die Engine3D-Headerdatei wird durchlaufen. In ihr wird das erste mal die _d3d9-Variable definiert.
Aufgrund des #pragma once in dieser Datei können andere #include "Engine3D.h"-Anweisungen da nicht nochmal rüberlaufen und die Variable erneut definieren.
Aber das geschieht doch, sobald ich in einer zweiten CPP-Datei (hier ja die ResourceManager.cpp) "#include "Engine3D.h" schreibe.
Die Projektausgabe sagt dazu auch folgendes:

Quellcode

1
2
3
4
5
6
7
1>------ Erstellen gestartet: Projekt: Engine3D, Konfiguration: Debug Win32 ------
1>  Engine3D.cpp
1>  Code wird generiert...
1>  Kompilieren...
1>  ResourceManager.cpp
1>  Code wird generiert...
1>Engine3D.obj : error LNK2005: "struct IDirect3D9 * Engine3D::_d3d9" (?_d3d9@Engine3D@@3PAUIDirect3D9@@A) ist bereits in ResourceManager.obj definiert.


Ich bin völlig ratlos und versuche seit 1 Stunde vergebliches. Die Variable habe ich auch schon in eine eigene Headerdatei mal ausgelagert, die natürlich auch #pragma once hat. Ohne Erfolg.

Ich bin für jeden Ratschlag oder Gedankenanstoß dankbar, und direkte Problemlösungen sind natürlich auch super 8o
Besten Dank im Voraus an jeden Poster!

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

2

17.07.2011, 13:15

pragma once gilt immer nur für die aktuelle Übersetzungseinheit. Andere müssen die Header dann wieder einbinden (max 1x wegen dem pragma). Dann hast du allerdings 2x die Definition der globalen Variable.
-> Benutze keine globalen Variablen und falls doch musst extern bentuzen.

3

18.07.2011, 17:22

Hallo, danke für die schnelle Antwort!

Ich weiß, globale Variablen sind nicht das gelbe vom Ei. Zuvor hatte ich es in Kapselung einer Klasse versucht, aber es wurde mir dann doch zu friemelig.
Wie dem auch sei, extern hatte ich mir auch angesehen und nutzte es in meinem allerersten Projekt sogar. Nur habe ich es diemsla nicht mehr korrekt auf die Reihe bekommen, vermutlich aufgrund potentieller Unfähigkeit meinerseits. :)

Allerdings habe ich die globalen Variablen in die zugehörige CPP-Datei geschrieben (im obigen Beispiel wäre das also Engine3D.cpp; natürlich nach dem #include "Engine3D.h") und schon lässt es sich problemlos kompilieren.

Interessante Frage wäre nur, ob dass jedem vernünftigen C++-Programmierer die Haare zu Kopfe stehen lassen wird (mal abgesehen von dem Global-Aspekt).
Aber für meinen ersten Engine-Wurf scheint es zu reichen, nehme ich erstmal an.

Werbeanzeige