C++: Mehrfachdeklaration läßt sich nicht beseitigen

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
AspeLin
Beiträge: 664
Registriert: 19.06.2003 16:06:16
Wohnort: Berlin

C++: Mehrfachdeklaration läßt sich nicht beseitigen

Beitrag von AspeLin » 16.04.2006 14:47:31

Ich habe drei Klassen in drei Header-Dateien deklariert. Jede dieser Deklarationen ist von einem Block

Code: Alles auswählen

#ifndef KLASSE_X
#define KLASSE_X
...
#endif
umgeben. Die dazugehörigen Prozeduren und Funktionen stehen jeweils in klasse_x.cpp, die jedoch nicht nur ihre eigenen Header-Dateien "includen", also z.B. klasse_1.h aus klasse_1.cpp, sondern auch Header-Dateien der übrigen beiden Klassen. Ich möchte nämlich aus einer Klasse auch Funktionen aus einer anderen Klasse nutzen. main.cpp sieht so aus:

Code: Alles auswählen

#include <common.h>
#include <klasse_1.h>
#include <klasse_2.h>
#include <klasse_3.h>
...
klasse_1.cpp so:

Code: Alles auswählen

#include <common.h>
#include <klasse_1.h>
#include <klasse_2.h>
...
Man sieht also, es müßte eine Mehrfachdeklaration geben, die vom Linker auch bemängelt werden. Aber sollte das nicht der #ifndef-Block in den Headern verhindern? Ist es vielleicht unsauber bzw. unmöglich, in Funktionen einer Klasse Funktionen einer anderen Klasse zu verwenden? Wenn ich das richtig verstanden habe, dann spielt die Reihenfolge der #include-Statements auch eine Rolle. Irgendwie stehe ich mächtig auf dem Schlauch. :oops:
Täuschung ist das Silikon der Postmoderne.

aspettl
Beiträge: 318
Registriert: 15.02.2006 22:05:37
Lizenz eigener Beiträge: MIT Lizenz
Kontaktdaten:

Beitrag von aspettl » 16.04.2006 14:55:17

Könntest du konkret deinen Code angeben? D.h. die wichtigsten Teile und am besten auch die genaue Compiler-Fehlermeldung. An obenstehendem kann ich kein Problem sehen.

Mehrfachdeklarationen gibt es, wenn in einer "Datei" mehrfach das gleiche definiert wird. Das #include bringt den Precompiler nur dazu, die angegebene Datei 1:1 an dieser Stelle einzufügen. Wenn man dies nur mit Headerdateien macht, welche komplett in ifndef eingeschlossen sind, umgeht man die doppelte Deklaration sicher.

Gruß
Aaron

Benutzeravatar
AspeLin
Beiträge: 664
Registriert: 19.06.2003 16:06:16
Wohnort: Berlin

Beitrag von AspeLin » 16.04.2006 15:26:18

In meiner main.cpp steht

Code: Alles auswählen

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <common.h>
#include <map.h>
#include <draw.h>
#include <player.h>

using namespace std;
...
Dasselbe steht in player.cpp. Die erste Fehlermeldung lautet:

Code: Alles auswählen

player.o: In function `player':src/player.cpp:8: multiple definition of `fs_draw'
main.o:src/main.cpp:14: first defined here
Und draw.h sieht so aus:

Code: Alles auswählen

#ifndef STDDRAW_H
#define STDDRAW_H

using namespace std;

class draw{
  public:
    draw();
    ~draw();
    SDL_Surface *load_image(string filename);
    void apply_surface();
    bool load_graphics();
    void apply_surface(int x, int y, SDL_Surface* source, SDL_Surface* destination);
    void cell(int cell_x, int cell_y);
    void world(int cam_pos_x, int cam_pos_y);
    void status();
}fs_draw;

#endif
Sieht für mich aus, als würde der #ifndef-Block ignoriert. Welchen Grund kann es dafür geben?
Täuschung ist das Silikon der Postmoderne.

Benutzeravatar
Joghurt
Beiträge: 5244
Registriert: 30.01.2003 15:27:31
Wohnort: Hamburg
Kontaktdaten:

Beitrag von Joghurt » 16.04.2006 15:46:20

Das Problem ist, dass sowohl main.o als auch player.o eine Instanz von draw mit dem Namen "fs_draw" definiert haben.

Was du willst, ist wahrscheinlich

Code: Alles auswählen

extern class draw { ... } fs_draw;
Und draw.c enthält dann u.A.

Code: Alles auswählen

draw fs_draw;
Solche globalen Variablen sind aber schlechter C++-Stil.

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von gms » 16.04.2006 15:46:43

Der #ifndef Block verhindert nur, daß draw.h mehrmals in EINEM Modul includiert wird.

Ändere das einmal in:

Code: Alles auswählen

class draw {
 ...
};
extern draw fs_draw;
Gruß
gms

Benutzeravatar
AspeLin
Beiträge: 664
Registriert: 19.06.2003 16:06:16
Wohnort: Berlin

Beitrag von AspeLin » 16.04.2006 18:42:56

Das mit dem "extern" hat funktioniert, nachdem ich in main.cpp Objekte der Klassen erzeugt habe (was ich vorher gleich in den Headern gemacht hatte). Weil "extern" unsauberer Stil ist, muß ich die Daten einer Klasse an eine andere Klasse über ihre Funktionen und Prozeduren übergeben, richtig?
Ich war noch nie Fan von Objektorientierung, aber jetzt sehe ich schon etwas besser durch. Danke Euch.
Täuschung ist das Silikon der Postmoderne.

Antworten