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.04.2008, 21:53

Problem bei Vererbung und Benutzung von mehreren Dateien

Wie schon in der Überschrift zu betrachten ist habe ich ein Problem:

Ich habe einen Quellcode, der in ein "Main() Listing" und mehrere Klassendeklarationen in Headern sowie Funktionsdeklarationen der Klassen in .cpp Dateien unterteilt ist. Wenn ich nun versuche das Ganze zu kompilieren, sagt mein Compiler (VC 2008 Express) dass in allen meinen Funktionsdeklarationen ein unbekannter Bezeichner ist. Das sieht dann wie folgt aus:

error C2065: 'cout': nichtdeklarierter Bezeichner

trotzdem ist "cout" soweit ich mich entsinnen kann ein gültiger Befehl (hat auf jeden Fall bis jetzt immer Funktioniert...)

Ich denke also dass es was damit zu tun hat, dass die Codesegmente nich richtig miteinander "verbunden" sind.

hier mal die main Funktion und exemplarisch eine Klasse:

main Listing (meines erachtens nicht der Fehlerauslöser)

Quellcode

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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
#include <iostream>
#include "Basisklasse_ Soldat.h"
#include "Schwertkaempfer.h"
#include "Bogenschütze.h"
#include "Speerkämpfer.h"
#include "Reiter.h"
#include "Ritter.h"

using namespace std;

//Globale Variablen der Ressourcen
//
int Nahrung = 10000;
int Holz = 5000;
int Metall = 500;
int Gold = 400;
int Stein = 2500;
int Bev = 100;

//Hauptprogramm
//
int main ()
{
    //Zeugs zum Soldaten rekrutieren
    //Zeiger erstellen
    CSchwertkaempfer *pSchwertkaempfer = NULL;
    CBogenschuetze *pBogenschuetze = NULL;
    CSpeerkaempfer *pSpeerkaempfer = NULL;
    CReiter *pReiter = NULL;
    CRitter *pRitter = NULL;
    
    //Auswahlsvariable
    //
    int Auswahl;
    
    //Begrüßung
    //
    cout << "Willkommen in der Armee!\nDeine Auswahl?\n\n";
    
    //Menü
    //
    do
    {
        cout << "1 - Soldaten rekrutieren\n";
        cout << "2 - Infos zu den Soldaten anzeigen\n";
        cout << "3 - Armeestaerke anzeigen\n";
        cout << "4 - Programm beenden\n\n";
        
        //eingabe
        cin >> Auswahl;
        
        //je nach Auswahl verzweigen
        switch (Auswahl)
        {
            //Soldaten rekrutieren?
            case(1):
            {
                //Auswahlvariable
                int Menue;
                
                //Frage
                cout << "Was fuer einen Soldaten moechtest du rekrutieren?";
                
                //Untermenuü
                //
                do
                {
                    cout << "1 - Schwertkaempfer rekrutieren\n";
                    cout << "2 - Bogenschuetzen rekrutieren\n";
                    cout << "3 - Speerkaempfer rekrutieren\n";
                    cout << "4 - Reiter ausbilden\n";
                    cout << "5 - Ritter ausbilden\n";
                    cout << "6 - Zurueck zum Hauptmenue\n\n";
                    
                    //Eingabe
                    cin >> Menue;
                    
                    //Je nach Eingabe verzweigen
                    //
                    switch (Menue)
                    {
                        case(1):
                        {   
                            //Schwertkämpfer auf dem Heap initialisieren
                            pSchwertkaempfer = new CSchwertkaempfer ();
                            
                            //unbedingt dran denken: Speicher nachher freigeben
                        }break;
                        
                        case(2):
                        {
                            //Bogenschützen auf dem Heap erstellen
                            pBogenschuetze = new CBogenschuetze ();
                            
                            //Speicher nachher freigeben
                        }break;
                        
                        case(3):
                        {
                            //Speerkämpfer auf dem Heap erstellen
                            pSpeerkaempfer = new CSpeerkaempfer ();
                            
                            //Speicher nachher freigeben
                        }break;
                        
                        case(4):
                        {   
                            //Reiter auf dem Heap erstellen
                            pReiter = new CReiter ();
                            
                            //Speicher unbedingt nachher freigeben
                        }break;
                        
                        case(5):
                        {   
                            //Ritter auf dem Heap erstellen
                            pRitter = new CRitter ();
                            
                            //Speicher nachher freigeben
                        }break;
                        
                        //falsche Eingabe?
                        default:
                        {
                            cout << "Falsche Eingabe!\n\n";
                        }
                    }
                }while (Menue != 6);
            }break;
            
            //Infos anzeigen?
            case(2):
            {
                int NeueAuswahl;
                
                cout << "Zu welchem Soldaten moechtest du Informationen anzeigen lassen?\n";
                
                do
                {
                    cout << "1 - Infos zum Schwertkaempfer\n";
                    cout << "2 - Infos zum Bogenschuetzen\n";
                    cout << "3 - Infos zum Speerkaempfer\n";
                    cout << "4 - Infos zum Reiter\n";
                    cout << "5 - Infos zum Ritter\n";
                    cout << "6 - Zurueck zum Hauptmenue\n\n";
                    
                    //Eingabe
                    cin >> NeueAuswahl;
                    
                    //je nach Eingabe verzweigen
                    switch (NeueAuswahl)
                    {
                        case(1):
                        {
                            pSchwertkaempfer -> ZeigeDatenSchwertkaempfer ();
                        }break;
                        
                        case(2):
                        {
                            pBogenschuetze -> ZeigeDatenBogenschuetze ();
                        }break;
                        
                        case(3):
                        {
                            pSpeerkaempfer -> ZeigeDatenSpeerkaempfer ();
                        }break;
                        
                        case(4):
                        {
                            pReiter -> ZeigeDatenReiter ();
                        }break;
                        
                        case(5):
                        {
                            pRitter -> ZeigeDatenRitter ();
                        }break;
                        
                        //Falsche Eingabe
                        default:
                        {
                            cout << "Falsche Eingabe!\n";
                        }
                    }
                }while (NeueAuswahl != 6);
            }break;
            
            //Armeestärke anzeigen?
            case(3):
            {
                cout << "Deine Armee umfasst " << 100 - Bev << " Soldaten";
                cout << "\nDavon sind: \n";
                cout << pSchwertkaempfer -> AnzahlSoldaten << " Soldaten Schwertkaempfer, \n";
                cout << pBogenschuetze -> AnzahlSoldaten << " Soldaten Bogenschuetzen, \n";
                cout << pSpeerkaempfer -> AnzahlSoldaten << " Soldaten Speerkaempfer, \n";
                cout << pReiter -> AnzahlSoldaten << " Soldaten Reiter, \n";
                cout << pRitter -> AnzahlSoldaten << " Soldaten Ritter, \n";
            }break;
            
            //Falsche Eingabe?
            default:
            {
                cout << "Falsche Eingabe!\n";
            }
        }
    }while(Auswahl != 4);      //Spiel beenden
    
    cout << "Bis zum naechsten Mal\n";
    
    //Speicher freigeben
    delete pSchwertkaempfer;
    pSchwertkaempfer = NULL;
    
    delete pBogenschuetze;
    pBogenschuetze = NULL;
    
    delete pSpeerkaempfer;
    pSpeerkaempfer = NULL;
    
    delete pReiter;
    pReiter = NULL;
    
    delete pRitter;
    pRitter = NULL;
    
    system("PAUSE");
    
    return 0;
}


Ich weiß globale Variablen sind eigentlich "Böse" aber hier fand ich sie angebracht...(freue mich über verbesserungsvorschläge)

und hier der "Speerkämpfer:

Basisklasse

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//Hier wird die Basisklasse des Soldaten deklariert
//ale wichtigen Sachen von Soldaten sind hier drin
//
class CSoldat
{
    protected:
    
        //Membervariablen
        //
        //Werte
        //
        int m_Lebenspunkte;
        int m_Angriff;
        float m_fGeschwindigkeit;
        int m_Ruestung;
        
    public:
        
        //Anzahl der erstellten Soldaten
        int AnzahlSoldaten;
};


Header

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//Klasse des Speerkämpfers
//abgeleitet von CSoldat
//

#include "Basisklasse_ Soldat.h"

class CSpeerkaempfer : public CSoldat
{
    //Alle Membervariablen sind in "CSoldat"
    public:
    
        //Memberfunktionen
             CSpeerkaempfer ();       //Konstruktor
        void ZeigeDatenSpeerkaempfer ();
};


Speerkämpfer.cpp

Quellcode

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
//Funktionsdeklaration für den Speerkämpfer
//

#include "Speerkämpfer.h"

//globale Variablen einfügen
extern int Nahrung;
extern int Holz;
extern int Stein;
extern int Metall;
extern int Gold;
extern int Bev;

//Konstruktor
//
//Aufgabe: Speerkämpfer registrieren und initialisieren
//---------------------------------------------------------------------------------------
CSpeerkaempfer::CSpeerkaempfer ()
{
    //Jetzt haben wir einen Speerkämpfer mehr
    AnzahlSoldaten++;
    
    //Standardwerte initialisieren
    m_Lebenspunkte = 100;
    m_Angriff = 50;
    m_fGeschwindigkeit = 1.25f;
    m_Ruestung = 2;
    
    //Kosten des Speerkämpfers vom Ressourcenpool abziehen
    Nahrung -= 150;
    Metall -= 5;
    Holz -= 250;
    Gold -= 20;
    Bev--;
    
    cout << "Speerkaempfer wurde ausgebildet\n\n";
}//Konstruktor
//---------------------------------------------------------------------------------------

//ZeigeDatenSpeerkaempfer
//
//Aufgabe: Beschreibung des Speerkämpfers ausgeben
//
void CSpeerkaempfer::ZeigeDatenSpeerkaempfer ()
{
    cout << "Kosten: \n";
    cout << "Nahrung: 150\n";
    cout << "Holz: 250\n";
    cout << "Metall: 5\n";
    cout << "Gold: 20\n";
    cout << "Bevoelkerungspunkte: 1\n";
    
    cout << "Insert description here...\n\n";
}//ZeigeDatenSpeerkämpfer
//--------------------------------------------------------------------------------------------


Ich denke jeder der sich durchgelesen hat wird erkannt haben, dass es sich dabei um eine "Armeeverwaltung handelt, ähnlich der in einem RTS, die Soldaten rekrutieren und deren Status anzeigen soll (alles leicht pseudo-mäßig, schon wegen der Konsole, aber ich bin eben noch ein Anfänger)

jeder der meine Fehler findet erntet meinen unendlichen Dank. Ich sitz jetzt schon seit ein Paar tagen an diesem Viech und verbringe die meiste Zeit eig nur mit Fehler suchen^^ Also vielen Dank schon mal an jeden der sich durch meine "Quellcode" durchschlägt.

in diesem Sinne mfg

euer C++ Anfänger

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

2

03.04.2008, 21:59

nur weil du in main.cpp using namespace std; geschrieben hast, bedeutet das nicht, dass es in allen andren .cpp dateien auch so is ;)

3

04.04.2008, 15:33

Das heißt ich muss nur in jeder Datei "using namespace std;" einfügen und das wars?!?

wenn das Leben nur immer so einfach wäre^^

vielen Dank, ich werds gleich mal austesten

€dit: so beinahe alle Fehler sind weg...nur noch einer is da:

in der Basisklasse CSoldat: "error C2011: 'CSoldat': 'class' Typneudefinition"

was genau ist bitte "Typneudefinition"?

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

4

04.04.2008, 15:54

Zitat von »"Un{}normaL"«

Das heißt ich muss nur in jeder Datei "using namespace std;" einfügen und das wars?!?


naja, das is eine möglichkeit. schöner wärs, wenn du einfach std::cout statt nur cout machst und auf das using verzichtest, oder using std::cout; machst und nicht gleich den ganzen namespace hereinholst ;)

Zitat von »"Un{}normaL"«

€dit: so beinahe alle Fehler sind weg...nur noch einer is da:

in der Basisklasse CSoldat: "error C2011: 'CSoldat': 'class' Typneudefinition"

was genau ist bitte "Typneudefinition"?


das bedeutet dass eine zweite definition der klasse CSoldat vorliegt.
könnte z.b. daran liegen, dass du einen header irgendwie zweimal einbindest (z.b. noch einmal über einen anderen header).

include guards dürften das problem lösen ;)

5

04.04.2008, 16:02

heißt das dann dass ich die Zeile

#include "Basisklasse_ Soldat.h"

bei jeder Klasse raustun kann oder ist das nicht das Problem?

nen 2. Header kann ich auf Anhieb nich erkennen und was include guards sind weiß ich leider auch nich^^

naja ich schau mal weiter nach nem zweiten header und guck mal dass ich das mit dem namespace etwas eleganter mach' :D

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

6

04.04.2008, 16:08

z.b. in main.cpp inkludierst du zuerst "Basisklasse_ Soldat.h" und dann "Speerkämpfer.h". letzteres inkludiert aber "Basisklasse_ Soldat.h" schon selber -> indirekt doppeltes include...

7

04.04.2008, 16:12

ok die Basisklasse is raus aus main.cpp. Jetzt hab ich aber 5 (glaub ich) Klassen die diese Klasse jeweils auch inkludieren...hab ich dann wenn ich die Basisklasse 5 mal indirekt inkludiere diese auch 5 mal deklariert und wenn ja, wie löse ich das?

€dit: ich hab mich mal knapp nach include guards in Google umgeschaut: sind das die Dinger, die mit "#ifndef" anfangen und mit "#endif" aufhören?
bzw würden die mein Problem lösen?

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

8

04.04.2008, 17:07

Zitat von »"Un{}normaL"«

ok die Basisklasse is raus aus main.cpp. Jetzt hab ich aber 5 (glaub ich) Klassen die diese Klasse jeweils auch inkludieren...hab ich dann wenn ich die Basisklasse 5 mal indirekt inkludiere diese auch 5 mal deklariert und wenn ja, wie löse ich das?

€dit: ich hab mich mal knapp nach include guards in Google umgeschaut: sind das die Dinger, die mit "#ifndef" anfangen und mit "#endif" aufhören?
bzw würden die mein Problem lösen?


Ja das sind die Includeguards. (Kannst bei dem VC auch noch #pragma once machen; ist beim compilen schneller..)

Wenn du jetzt deine Objekte schön in header und die source unterteilst sollte das dein Problem lösen.

9

04.04.2008, 18:36

ich hab das jetzt mal versucht mit denen zu compilen und da kam folgende Fehlermeldung raus:

fatal error C1016: #if[n]def erfordert einen Bezeichner

offensichtlich is die Sache doch nich ganz so einfach oder ich hab was falsch gemacht. Hier is jedefalls meine überarbeitete Basisklasse:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#ifndef CSoldat

class CSoldat
{
    protected:
    
        //Membervariablen
        //
        //Werte
        //
        int m_Lebenspunkte;
        int m_Angriff;
        float m_fGeschwindigkeit;
        int m_Ruestung;
        
    public:
        
        //Anzahl der erstellten Soldaten
        int AnzahlSoldaten;
};

#endif


hab ich da nen Fehler bei der Verwendung der include guards gemacht?

ich möchte mich darüber hinaus nochmals bei allen bedanken, die sich die Zeit für mich genommen haben und mein Problem angeschaut haben...Dankeschön

€dit: hab jetzt was anderes ausprobiert und auch meinen Code entsprechend hier im Forum angepasst, Jetzt sagt mir der Compiler wieder das mit der Typneudefinition: irgendwas hab ich bei der Verwendung von include guards ganz sicher nich verstanden...

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

10

04.04.2008, 19:01

Includeguards machst du im allgemeinen wie folgt:

C-/C++-Quelltext

1
2
3
4
5
6
#ifndef DEINGUARD
#define DEINGUARD

// code


#endif


Wobei "DEINGUARD" am besten irgendwas ganz Eindeutiges ist, z.B. der Dateiname. Manche verwenden sogar Dateinamen + GUID, ich z.B. verwende immer __FILENAME_H_.
@D13_Dreinig

Werbeanzeige