Anfänger-Probleme mit Klassen

Rene42

Erfahrenes Mitglied
Hi Leute,

bin gerade dabei von Basic auf C++ umzusteigen. Vom Prinzip ist mir die Verwendung von Klassen klar. Nun habe ich die Klassen in der Headerdatei "Editor.h" abgelegt.
Diese sieht folgendermasen aus:
Code:
//Editor Header Datei Version 1.0

#include <string>
#include <iostream>

//Klasse für ein Spielbrett
class Brett {
             public:
             string Spieler;
             int Punkte;
             int Spielstand;
             char Farbe;
             string Uhrzeit;
             string Kommentar;
             
             void function WriteIn()
                  {
                   cout<<"Geben Sie bitte den Namen des Spielers ein!";
                   cin>>this.Spieler;                
                  }
             
             
            }

//Klasse für einen kompletten Spielbericht
class Spielbericht {
                    public:
                    string Paarung;
                    string Datum;
                    string Runde;
                    string Spielort;
                    Brett Bretter[8];                    
                   }

Als erstes ergibt sich das Problem, dass String unbekannt ist. In einem Tutorial hatte ich gelesen, dass String als Typ verwendet werden kann wenn ich ich die Datei String einbinde..... Außerdem meldet der Compiler auch den Fehler, dass die der Typ function unbekannt ist.
Des Weiteren verwende ich in der Main.cpp Datei folgenden Code, um die WriteIn Funktion zu benutzen:

Code:
//CPP-Editor Version 1.0

#include <cstdlib>
#include <iostream>
#include <Editor.h>



int main()
{
    Brett Test;
    Test.WriteIn();
    system("PAUSE");
    return 0;
}

Hier entstehen folgende Probleme. "Brett" ist ein unbekannter Typ, obwohl die Klassendefinition eingebunden ist.

Hoffe auf hilfreiche Tipss

Gruß Rene42
 
C++ ist nur an mir vorbei gezogen, doch soweit ich mich richtig erinnere,
werden die Funktionen / Methoden in einer Datei nur "angemeldet" und dann in einer weiteren Datei mit Rumpf angegeben.

void Methode (void);

und dann in der nächsten die genaue Definition.

Du weißt also quasi den Compiler darauf hin, dass du eine zugängliche Methode anmelden möchtest und verweist auf den
Pfad, wo er sie finden kann.

LG
 
Moin,

na, da gibt es ja so einiges anzumerken ... :)

Vorab: mit welchem System/Compiler arbeitest Du denn ?

bin gerade dabei von Basic auf C++ umzusteigen. Vom Prinzip ist mir die Verwendung von Klassen klar. Nun habe ich die Klassen in der Headerdatei "Editor.h" abgelegt.
Diese sieht folgendermasen aus:
Code:
//Editor Header Datei Version 1.0

#include <string>
#include <iostream>

//Klasse für ein Spielbrett
class Brett {
             public:
             string Spieler;
             int Punkte;
             int Spielstand;
             char Farbe;
             string Uhrzeit;
             string Kommentar;
             
             void function WriteIn()
                  {
                   cout<<"Geben Sie bitte den Namen des Spielers ein!";
                   cin>>this.Spieler;                
                  }
             
             
            }

//Klasse für einen kompletten Spielbericht
class Spielbericht {
                    public:
                    string Paarung;
                    string Datum;
                    string Runde;
                    string Spielort;
                    Brett Bretter[8];                    
                   }
Als erstes ergibt sich das Problem, dass String unbekannt ist. In einem Tutorial hatte ich gelesen, dass String als Typ verwendet werden kann wenn ich ich die Datei String einbinde..... Außerdem meldet der Compiler auch den Fehler, dass die der Typ function unbekannt ist.
Des Weiteren verwende ich in der Main.cpp Datei folgenden Code, um die WriteIn Funktion zu benutzen:

Code:
//CPP-Editor Version 1.0

#include <cstdlib>
#include <iostream>
#include <Editor.h>



int main()
{
    Brett Test;
    Test.WriteIn();
    system("PAUSE");
    return 0;
}
Hier entstehen folgende Probleme. "Brett" ist ein unbekannter Typ, obwohl die Klassendefinition eingebunden ist.


(a) Du musst für JEDE Klasse einen eigenen Header anlegen, also "Brett.h" und "Spielbericht.h"
(b) Funktionen, wie Dein "Writeln" dürfen nicht im Header, sondern im zugehörigen Quellcode (also "Brett.cpp" und "Spielbericht.cpp") stehen
(c) die String wird er nicht kennen, da Du den Header falsch einbindest! #include <string.h> wäre in diesem Fall die richtige Art
(d) genau so musst Du dann Deine beiden Header "Brett.h" und "Spielbericht.h" in die Hauptklasse Deines Programms einbinden

So, dies mal so auf die Schnelle ... ich würde aber dringend raten,erstmal mehr mit den Grundlagen von C++ zu beschäftigen, sonst stößt Du immer wieder schnell auf gleichartige Probleme!

Gruß
Klaus
 
Hallo, ich kann zwar nicht auf Problemen anderer eingehen, aber bezieht man eigene Headerdateien mit #include "Editor.h"?
Außerdem meldet der Compiler auch den Fehler, dass die der Typ function unbekannt ist.
Was sucht da function, ich selber weiß nichts von einem Typ function, das müsste dan wegfallen, this is ein Zeiger, das heißt, du kannst nicht mit dem Punkt (Operator?) arbeiten, du musst '->' nehmen
mit typ string kann ich dir auch nicht helfen
meine Idee wäre dann ein ganz normales Array zu nehmen
also hier deine Klasse:
Code:
#include <cstdlib>
#include <iostream>

using namespace std;

//Klasse für ein Spielbrett
class Brett {
             public:
             char Spieler[20];
             int Punkte;
             int Spielstand;
             char Farbe;
             string Uhrzeit;
             string Kommentar;
             
             void WriteIn()
                  {
                   cout<<"Geben Sie bitte den Namen des Spielers ein!";
				   cin>>Spieler;           
                  }
             
             
            };

//Klasse für einen kompletten Spielbericht
class Spielbericht {
                    public:
                    string Paarung;
                    string Datum;
                    string Runde;
                    string Spielort;
                    Brett Bretter[8];                    
                   };
 
Als erstes hab ich mal fix das .h hinter string ergänzt, was aber leider nix gebracht hat.

Also ist für jede Klasse eine eigene Header anzulegen. Die Funktionen werden dann nur im Header "angekündigt" und in der .cpp erst gepostet. Ist das so korrekt.
 
Also laut meinem Buch sollte die Klasse string so eingebunden werden
C++:
#include <string>
Der Fehler liegt daran das du das
C++:
using namespace std;
nicht benutzt hast.

Falls du das nicht nutzt müsstest du bei jedem string schrieben:
C++:
 std::string variable;

Gruß Jennesta

€Achja noch einen Nachtrag zu den Klassen. So sollte das prinzipiell aussehen:

C++:
// Klasse.h

class Klasse {
private:
	int zahl;			// Variable
	void schreibe();	// Funktion
}

C++:
// Klasse.cpp

Klasse::schreibe() {
	cout << zahl;		
}

Natürlich muss zahl hier einen gültigen Wert besitzen.
 
Zuletzt bearbeitet:
Danke, dass du das nochmal so ausführlich beschrieben hast, meine Frage wie weiss die main Funktion in Main.cpp von dem was in Klasse.cpp steht...

PS: Ich zieh ne Schurkenkarte.....die Friends...
 
Zuletzt bearbeitet:
Achja du musst in der main.cpp die header-datei deiner Klasse includieren außerdem musst du diese auch in der Klasse.cpp includieren und zwar mit

C++:
#include "Klasse.h"

Den Rest macht der Linker beim kompilieren.

€dit : Ach undleider muss ich dich korrigieren es war die Schuftkarte ;) Aber gut aufgepasst^^
 
Hier sind erstmal ein paar theoretische Grundlagen.
Anders als in Basic gibt es in C/C++ zwei Arten von Code-Dateien.
  • die Header-Datei mit der Endung .h oder .hpp, wo die Klassen deklariert werden
  • die Code-Datei mit der Endung .c oder .cpp, wo die Methoden definiert, d.h. implementiert, werden

Nach der Deklaration einer Klasse muss ein Semikolon folgen; das hast du in deiner Header-Datei nicht gemacht.
Die Deklaration deiner Klasse Spielbericht ist formal korrekt, und sie braucht auch keine weitere Implementierungsdatei, weil für sie keine Methoden deklariert wurden.
Die Deklaration deiner Klasse Brett ist nicht korrekt. Erstens gibt es für die Deklaration einer Methode kein extra Schlüsselwort function oder ähnliches, wie es in z.B. in Basic oder JavaScript verwendet wird; der Compiler erkennt eine Funktion daran, dass dem Bezeichner (der Name) Funktion eine Parameterliste folgt - das sind die runden Klammern - , die auch leer sein kann; dann wird manchmal auch das Schlüsselwort void verwendet also z.B. WriteIn(void), es ist aber kein Muss. Zweitens wird die Methode in der Headerdatei nur deklariert, d.h. es werden Rückgabetyp, Name und der Aufbau der Parameterliste angegeben; die eigentliche Implementierung geschieht in der Coder-Datei. Es genügt, in der Parameterliste die Typen anzugeben, die Namen der Parameter können weggelassen werden. Du hast aber auch die Möglichkeit, eine Funktion als inline zu deklarieren, dann muss der Code tatsächlich in der Headerdatei erscheinen; das Schlüsselwort inline muss dann vor dem Rückgabetyp stehen; in deinem Fall sähe es dann so aus: inline void WriteIn(){<dein Code>};. Deine Methode ist also korrekt, wenn du das Wort function weglässt und inline vor void schreibst.
Wie die Trennung von Deklaration und Implementierung gemacht wird, hat Jennesta schon ganz gut erklärt.
Du brauchst in deiner Headerdatei nur diejenigen Headerdateien anzugeben, die für die Typen notwendig sind, die du in ihr verwendest. Wenn du also dich dazu durchringst, deine Methode WriteIn in der Headerdatei nur zu deklarieren, dann brauchst du iostream nur in der Codedatei einzubinden, nicht in der Headerdatei.
Übrigens ist es nicht notwendig und manchmal auch nicht zweckdienlich, für jede Klasse eine eigene Header- und Codedatei zu erstellen, es ist 'nur' guter Stil.

Noch ein paar Worte zur Trennung von Header- und Code-Datei. Die Headerdatei dient dazu, dass der Compiler z.B. Typüberprüfungen durchführen kann, d.h. ob eine Klasse bekannt ist, die verwendeten Methoden vorhanden sind, die Parameter korrekte Typen haben etc. Dafür braucht er nicht zu wissen, wie die Implementierung aussieht, deswegen wird diese in eine gesonderte Datei ausgelagert, die Code-Datei. Der Compiler erzeugt aus jeder Code-Datei eine Objektdatei mit der Endung .o, die alleine nicht lauffähig ist, aber schon die komplette Übersetzung der Implementierung in Maschinencode ist, inklusive aller Referenzen auf andere Module und/oder Bibliotheken. Um diese einzelnen Objektdateien in eine einzige Programm- oder Bibliotheksdatei zu vereinigen, existiert der Linker; in den meisten Entwicklungsumgebungen brauchst du ihn nicht extra zu starten, das geschieht automatisch, wenn du 'Projekt übersetzen' wählst/drückst (oder wie immer auch das bei dir heißt). Diese Modularisierung hat den Vorteil, dass immer nur diejenigen Dateien compiliert werden müssen, wo Änderungen vorgenommen wurden; das spart Arbeit und somit auch Zeit.

Und hier ist eine Seite mit Büchern über C++ zu Herunterladen und ein Online-Tutorial.
 
Zuletzt bearbeitet:
Bitte gebt doch Anfängern nicht so viele falsche Tipps... :(

(a) Du musst für JEDE Klasse einen eigenen Header anlegen, also "Brett.h" und "Spielbericht.h"
Nein, muss man nicht. Kann man bzw. sollte man vielleicht, aber ein Zwang besteht nicht.
(b) Funktionen, wie Dein "Writeln" dürfen nicht im Header, sondern im zugehörigen Quellcode (also "Brett.cpp" und "Spielbericht.cpp") stehen
Es gibt keine Einschränkung, was im Header stehen darf und was nicht.
(c) die String wird er nicht kennen, da Du den Header falsch einbindest! #include <string.h> wäre in diesem Fall die richtige Art
Falsch! Header aus der C++-Standardbibliothek besitzen keine Endung.

Der Fehler liegt daran das du das
C++:
using namespace std;
nicht benutzt hast.
In einem Header eine using-Direktive zu verwenden, wäre allerdings ein Fehler – zumindest ein stilistischer. „Namespace Pollution“ lautet das Stichwort.

€Achja noch einen Nachtrag zu den Klassen. So sollte das prinzipiell aussehen:

C++:
// Klasse.h

class Klasse {
private:
	int zahl;			// Variable
	void schreibe();	// Funktion
}

C++:
// Klasse.cpp

Klasse::schreibe() {
	cout << zahl;		
}
Den Rückgabetyp void muss man bei der Definition nochmals aufführen und kann nicht einfach weggelassen werden.

Grüße,
Matthias
 
Zurück