Anfängerproblem: Klassen benötigen gegenseitig eine Deklaration der jeweils Anderen
-
volkard schrieb:
Dann mußt Du aber auch Nägel mit Köpfen machen und eine Fahrrad& getFahrrad() anbieten, einfach nur so, weil es einen Algorithmus geben könnte, der eun Fahrrad brauchen könnte.
Nein, im Gegensatz zu der Entscheidung 2 x double <-> double[2] wäre das ein Eingriff ins Interface der Klasse, der zu dem Zeitpunkt (noch) nicht nötig ist.
-
@pumuckl & Sebastian Pizer,
Wieso nicht eher sowas?struct Vec2d { double x; double y; double& operator [](std::size_t index) { assert(index < 2); return (index == 0 ? x : y); } double operator [](std::size_t index) const { assert(index < 2); return (index == 0 ? x : y); } };Würde ich irgendwie als schöner empfinden

Grüssli
-
Dravere schrieb:
@pumuckl & Sebastian Pizer,
Wieso nicht eher sowas?Die obige Version läßt sich ohne Mühe und Umdenken auch für drei oder vier Dimensionen nehmen. Und sie kostet gar nichts, was man von einem if nicht sagen kann. Wenn man Indexzugriffe erlauben will, ist sie wohl die hübscheste.
-
Nochmal zu meinem Problem^^.
Ich habe den Aufruf jetzt geändert, jetzt erzeugt er keinen Fehler mehr. Doch plötzlich passt dem Compiler wieder alles nicht. Ich könnte mir die Haare ausreißen!

Zu der Definition der Funktionen in der Klasse Spieler, hier:
#ifndef _SPIELER_H_ #define _SPIELER_H_ #include "Spieler.h" #endif Spieler::Spieler(int* SpielfeldversatzX, int* SpielfeldX, int* SpielfeldversatzY, int* SpielfeldY, int AILevel) : dPosX(*SpielfeldversatzX + *SpielfeldX/7 - *SpielfeldX/40), dPosY(*SpielfeldversatzY + *SpielfeldY/2 - *SpielfeldX/8), w(*SpielfeldX/82.6), //82 zwei drittel h(*SpielfeldX/16.5), //16 acht fünfzehntel Punkte(0), AILevel(AILevel), dSpeedY(0){} ...Meint er plötzlich:
C:\...\Spieler.cpp|11|error: `Spieler' has not been declared|Und halt alle daraus resultierenden Fehler. Spieler.h ist doch eingebunden. Wieso fängt der Compiler jetzt damit an? Bis eben waren die flasch formulierten Reset()-Aufrüfe die beiden letzten Fehler gewesen.
-
Deine Include-Guards gehören imho in die Header-Datei...
-
asdasdasd schrieb:
Deine Include-Guards gehören imho in die Header-Datei...
d.h.:
/* *.cpp */ #include "Spieler.h" Spieler::Spieler(int* SpielfeldversatzX/*....*/) {}/* *.h */ #ifndef H_SPIELER_INCLUDED_ #define H_SPIELER_INCLUDED_ class Spieler { /*...*/ }; #endif //#ifndef H_SPIELER_INCLUDED_bb
-
Habs jetzt geändert, aber das ist ja nur Formsache und ändern nichts an dem Problem, dass Spieler.h einfach ignoriert wird.
-
Little Programmer schrieb:
Habs jetzt geändert, aber das ist ja nur Formsache und ändern nichts an dem Problem, dass Spieler.h einfach ignoriert wird.
Nein, ist es nicht. Wenn du die Guards auch im Header hast, dann wird dessen Inhalt auch nicht eingebunden. Ist dir wirklich klar, was #define macht?
-
Wenn ich den Header nur mit Guards einbinde, wird er auch nicht eingebunden. ist nur mehr schreibarbeit mit dem selben Resultat. An den Fehlern hat sich auch gar nichts geändert.
-
Little Programmer schrieb:
An den Fehlern hat sich auch gar nichts geändert.
Dann aber nur, weil du einen Fehler gemacht hast...
Zeig mal den Header...bb
-
Also, der Anfang von Spieler.cpp:
#include "C:/Programme/CodeBlocks/SDL-1.2.13/include/SDL.h" #include "Spieler.h" Spieler::Spieler(int* SpielfeldversatzX, int* SpielfeldX, int* SpielfeldversatzY, int* SpielfeldY, int AILevel) : dPosX(*SpielfeldversatzX + *SpielfeldX/7 - *SpielfeldX/40), dPosY(*SpielfeldversatzY + *SpielfeldY/2 - *SpielfeldX/8), w(*SpielfeldX/82.6), //82 zwei drittel h(*SpielfeldX/16.5), //16 acht fünfzehntel Punkte(0), AILevel(AILevel), dSpeedY(0){} ...Und der Header Spieler.h:
#ifndef _SPIELER_H_ #define _SPIELER_H_ class SDL_Surface; namespace Game { class Ball; class Spieler { friend void Game::Kollisionsabfrage(Ball &Ball, Spieler &Spieler); friend void Game::Kollisionsabfrage(SDL_Surface *screen, Spieler &Spieler1, Spieler &Spieler2, Ball &Ball, int* SpielfeldversatzX, int* SpielfeldX, int* SpielfeldversatzY, int* SpielfeldY); public: Spieler(int* SpielfeldversatzX, int* SpielfeldX, int* SpielfeldversatzY, int* SpielfeldY, int AILevel); void SpielerSteuerung(bool *laeuft, int* SpielfeldX, int* SpielfeldversatzY, int* SpielfeldY); void PositionBerechnen(); void Abdecken(SDL_Surface *screen); void Darstellen(SDL_Surface *screen); protected: double dPosX; double dPosY; int w; int h; int Punkte; int AILevel; //0 bedeutet es ist ein vom Spieler gesteuerter Spieler double dSpeedY; }; } #endif
-
Du musst die Definitionen vom Spieler natürlich auch im Namespace Game machen und nicht im globalen. So definierst du eine Klasse Game::Spieler und definierst eine Methode einer Klasse ::Spieler, die es garnicht gibt. Lies dir das Kapitel zu Namespaces und zur Namensauflösung im Buch deiner Wahl nochmal genauer durch.
-
Little Programmer schrieb:
#include "C:/Programme/CodeBlocks/SDL-1.2.13/include/SDL.h"Dafür gibt es Suchpfade. Füge C:/Programme/CodeBlocks/SDL-1.2.13/include/ zum Suchpfad für Include-Verzeichnisse hinzu und schreibe stattdessen #include "SDL.h".
Little Programmer schrieb:
#ifndef _SPIELER_H_ #define _SPIELER_H_ class SDL_Surface;Diese Deklaration sieht nach einem verzweifelten "Hack" aus, den man benötigt, wenn man sich nicht an Kapselung hält.
Little Programmer schrieb:
namespace Game { class Ball; class Spieler { friend void Game::Kollisionsabfrage(Ball &Ball, Spieler &Spieler); friend void Game::Kollisionsabfrage(SDL_Surface *screen, Spieler &Spieler1, Spieler &Spieler2, Ball &Ball, int* SpielfeldversatzX, int* SpielfeldX, int* SpielfeldversatzY, int* SpielfeldY);Diese friend-Deklarationen sehen nach einem verzweifelten "Hack" aus, den man benötigt, wenn man sich nicht an Kapselung hält.
Little Programmer schrieb:
public: Spieler(int* SpielfeldversatzX, int* SpielfeldX, int* SpielfeldversatzY, int* SpielfeldY, int AILevel); void SpielerSteuerung(bool *laeuft, int* SpielfeldX, int* SpielfeldversatzY, int* SpielfeldY); void PositionBerechnen(); void Abdecken(SDL_Surface *screen); void Darstellen(SDL_Surface *screen);Wozu diese vielen Zeiger?
Es gibt jedenfalls keinen guten Grund, friend-Deklarationen hier zu benutzen. Du kommst damit nur in die Bredouille mit den Vorwärtsdeklarationen und schaffst unnötige Abhängigkeiten.
Gruß,
SP
-
Klar, hatte überhaupt nicht dran gedacht, dass ich bei den Funktionen auch den Namespace angeben muss. Vielen Dank, war echt zu blöd für, daran zu denken.

Die Zeiger nehme ich, um die Variablen direkt zu ändern bzw. darauf zuzugreifen und im Speicher keine neue Kopie davon anlegen zu müssen.
Wenn ich die Kollisionsabfrage aber nicht als friend deklariere, brauche ich für jede Variable von einem Spieler und einem Ball-Objekt eine Wiedergabefunktion und eine Speicherfunktion, da die Kollisionsabfrage natürlich auch die Positionen und Geschwindigkeiten ändert. Das wäre ein Haufen mehr Quelltext und die Klassen wären danach noch viel offener, weil nicht nur die Kollisionsabfrage, sondern jede x-beliebige Funktion frei in ihren Variablen lesen und schreiben könnte. Das wäre ja nicht Sinn der Sache.
Sonst fällt mir keine andere Möglichkeit ein, dass ohne friend zu regeln. Wenn ihr eine wisst, ich lerne gerne, wie es besser geht.
