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

03.10.2008, 18:35

header die sich gegenseitig brauchen ?

hallo,

folgendes Problem, wenn man 2 Header hat die sich "gegenseitig brauchen", also das Header1 einen Pointer von Header2 braucht und Header2 einen pointer von Header1 braucht.

Hab dazu ein kurzes Beispiel geschrieben, um die Problematik besser darstellen zu können

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// main.cpp

#include "header1.h"
#include "header2.h"

void main(void)
{
};

// header1.h

#pragma once
#include "header2.h" //include von header2, da ein pointer davon gebraucht wird


class H1
{
    H2 *TestHeader2; //speicherplatz für einen H2 pointer anlegen

};

// header2.h

#pragma once
#include "header1.h" //include von header1, da ein pointer davon gebraucht wird


class H2
{
    H1 *TestHeader1; //speicherplatz für einen H1 pointer anlegen

};


wenn man das nun compiliert kommen folgende Fehler :( (der Übersichtlichkeitshalber hab ich den pfad vor den Header durch .. ersetzt)

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
1>main.cpp
..\header2.h(7) : error C2143: syntax error : missing ';' before '*'
..\header2.h(7) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
..\header2.h(7) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>header1.cpp
..\header2.h(7) : error C2143: syntax error : missing ';' before '*'
..\header2.h(7) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
..\header2.h(7) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>header2.cpp
..\header2.h(7) : error C2143: syntax error : missing ';' before '*'
..\header2.h(7) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
..st\header2.h(7) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int


Dies wäre eine mögliche Lösung, ist aber sehr ungewöhnlich und unsauber, denn war ruft schon mitten in einer class #include auf

C-/C++-Quelltext

1
2
3
4
5
6
7
8
// header1.h

#pragma once

class H1
{
    #include "header2.h" //include von header2, da ein pointer davon gebraucht wird

    H2 *TestHeader2; //speicherplatz für einen H2 pointer anlegen

};


Danke für Hilfe!

MfG, Timm

Anonymous

unregistriert

2

03.10.2008, 18:41

Stichwort: Forward-Declartion.

In der Header-Datei von der Klasse wo du die andere benötigst, machst du eine Forward-Declaration der Klasse die du benötigst.

In der Source-Datei der Klasse inkludierst du dann den Header (also die Real-Declaration) der Klasse die du benutzt.

Ein Include in einer Klasse zu stopfen ist nicht nur unschön, sondern auch illegal wenn es sich nicht um inline-Files oder Assembler-Files handelt.

edit:
Ein Beispiel ausm Kopf:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// #############################################################################

// A.hpp

class B; // << Forward-Declaration


class A
{
public:
    B* b;
    void do_something_with_b (void);
    void foobar (void);
};


// #############################################################################

// A.cpp

#include "a.hpp"
#include "b.hpp" // << Real-Declaration


void A::do_something_with_b (void)
{
    b->foobar ();
}

void A::foobar (void)
{
    std::cout << __FUNCTION__ << endl;
}


// #############################################################################

// B.hpp

class A; // << Forward-Declaration


class B
{
public:
    A* a;
    void do_something_with_a (void);
    void foobar (void);
};


// #############################################################################

// B.cpp

#include "b.hpp"
#include "a.hpp" // << Real-Declaration


void B::do_something_with_a (void)
{
    a->foobar ();
}

void B::foobar (void)
{
    std::cout << __FUNCTION__ << endl;
}


// #############################################################################

// main.cpp

#include "a.hpp"
#include "b.hpp"

int main (void)
{
        // instanziieren

    A a;
    B b;

        // verlinken

    a.b = &a;
    b.a = &b;

        // do something with a/b

    a.do_something_with_b ();
    b.do_something_with_a ();
}

3

03.10.2008, 18:46

Vielen Dank!
Hab mit dem Problem die letzten paar Stunden gekämpft, aber keine Lösung gefunden :(

Anonymous

unregistriert

4

03.10.2008, 18:48

Hab dir mal ein Beispiel gepostet. Keine Garantie obs läuft ;) war nur ausm Kopf.

Edit: Welchen Compiler benutzt du? void main (void) ist doch mehr als nur verboten? :shock:

5

03.10.2008, 18:55

verwende VS2008, das war aber nur ein sehr simples Beispiel ;-)

Anonymous

unregistriert

6

03.10.2008, 18:58

Ich wusste gar nicht das der sowas illegales noch unterstützt? Naja egal.

Also Klartext: Zwei Header dürfen sich nie gegenseitig benötigen, daher muss die Implementierung in cpp-Dateien ausgelagert werden die später die Objektdateien werden. Irgendwie muss der PräProzessor ja eine Baum-Struktur herleiten können aus dem ganzen Inkludierungsgewusel und das was ich da gepostet habe ist eine der gängigsten und "fehlerfreiesten" Methoden.

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

7

03.10.2008, 19:29

Zitat von »"unsigned long"«

Irgendwie muss der PräProzessor ja eine Baum-Struktur herleiten können aus dem ganzen Inkludierungsgewusel und das was ich da gepostet habe ist eine der gängigsten und "fehlerfreiesten" Methoden.

Wäre mir neu, dass der Präprozessor irgendeine Baumstruktur herleitet.
Der sieht einfach nur das #include, öffnet die Datei und tut so, als ob ihr Inhalt da stünde, wo das #include steht.

Anonymous

unregistriert

8

03.10.2008, 19:43

David Scherfgen
Das ist nicht neu, das ist noch aus den uralten C-Zeiten, da der PräProzessor von C++ (leider) der selbe ist wie in C. Er muss einen kompletten "Includierungsbaum" herleiten um den Inhalt zusammenzufarmen und zu verbinden.

Aus diesem Grund ist es nicht möglich kreisartige oder netzartige Inkludierungsreihenfolgen mit dem PräProzessor herzuleiten, sondern nur hierarische bzw. polyhierarische Verbindungen. Der PräProzessor haut einen schon vor die Nase wenn man versucht den Diamond-Conflict herbeizubeschwören durch #include ;)

Man merkt aber schon sehr schön, dass er eine Art Baum aufbaut - würde er das nicht, warum schlägt er bei Mehrfachinkludierungen ohne Include Guards nur in einer gewissen Reihenfolge fehl? Weil er sich immer einen Startpunkt sucht und von da aus tiefer in die Verschachtelung geht ;)

Man kann das Verfahren wie mit der FireWire-Verkabelung vergleichen.

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

9

03.10.2008, 23:44

Zitat von »"unsigned long"«

Das ist nicht neu, das ist noch aus den uralten C-Zeiten, da der PräProzessor von C++ (leider) der selbe ist wie in C. Er muss einen kompletten "Includierungsbaum" herleiten um den Inhalt zusammenzufarmen und zu verbinden.

Das machen vielleicht einige Compiler, um rauszufinden, welche Dateien sie neukompilieren müssen, wenn was geändert wurde. Aber von "müssen" kann hier keine Rede sein. Der Präprozessor muss einfach nur das #include durch den Inhalt der eingebundenen Datei ersetzen.
Wenn du mir nicht glaubst, hier ist der Teil aus dem Standard:

Zitat von »"http://www.open-std.org/jtc1/sc22/open/n2356/"«

2 A preprocessing directive of the form
# include <h-char-sequence> new-line
searches a sequence of implementation-defined places for a header
identified uniquely by the specified sequence between the < and >
delimiters, and causes the replacement of that directive by the entire
contents of the header
. How the places are specified or the header
identified is implementation-defined.


Zitat von »"unsigned long"«

Aus diesem Grund ist es nicht möglich kreisartige oder netzartige Inkludierungsreihenfolgen mit dem PräProzessor herzuleiten, sondern nur hierarische bzw. polyhierarische Verbindungen.

Das ist der Fall, weil er sich sonst beim Ersetzen in eine Endlosschleife begeben würde.

Zitat von »"unsigned long"«

warum schlägt er bei Mehrfachinkludierungen ohne Include Guards nur in einer gewissen Reihenfolge fehl?

Kannst du dazu mal ein Beispiel angeben?

Werbeanzeige