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

27.09.2009, 19:16

2 Klassen verbinden ohne Vererbung

Hallo,

ich möchte gerne 2 Klassen (CGame und CIntro) zusammen verbinden, so das ich ohne viel getue und übergeben in der Main-Funktion die CGame Klasse voll in der CIntro Klasse verwenden kann.
Ich hoffe ich habe es richtig erklärt, ich selber kann es nämlich nicht besser erklären :D
Ich werde mal die entsprechenden Codezeilen posten:

Game.h

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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#ifndef _GAME_h
#define _GAME_h

#include "AllHeaders.h"

class CIntro;

class CGame
{
protected:
    sf::RenderWindow            MainWindow;
    sf::Event                   Event;
    int                         State;
    bool                        Running;
    //CIntro

    CIntro                      Intro;

public:

    //InitFunktion

    void InitGame(int Height, int Width, int Colour);
    ///

    sf::Font MyFont;
    sf::String Text;
    ///

    //Die 3 Spielzustände

    
    //IntroState ( 1 )

    void                            IntroState(void);
    //MenueState ( 2 )

    void                            MenueState(void);
    //MainState  ( 3 )

    void                            MainState(void);


    //Instanz von sich selbst

    static CGame* Instance() 
    {
        return &i_CGame;
    }


    //Methoden für State


    //Methode um Spielzustand zu bekommen

    int CurrentState(void)
    {
        return this->State;
    };

    //Methode um Spielzustand zu erhöhen

    void NextState(void)
    {
        if (this->State == 3)
        this->State = 1;
        else if (this->State == 1)
        this->State = 2;
        else if (this->State == 2)
        this->State = 3;
    };

    //Methode um Spielzustand zu senken

    void PreviousState(void)
    {
        if(this->State == 1)
        this->State = 3;
        else if (this->State == 3)
        this->State = 2;
        else if (this->State == 2)
        this->State = 1;
    };

    //Methode um Spielzustand seperat zu ändern

    // 1 = Introstate

    // 2 = Menuestate

    // 3 = Mainstate

    void ChangeState(int NewState)
    {
        if (NewState > 0 && NewState < 4)
            this->State = NewState;
    };

    //Methode um herrauszufinden, ob Game läuft

    bool IsRunning(void)
    {
        return this->Running;
    };

private:
    static CGame i_CGame;

};

#endif



Entsprechender Teil von Game.cpp

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
void CGame::IntroState()
{

//Wichtige Zeile, um die es sich handelt.

//Wichtige Zeile, um die es sich handelt.

//Wichtige Zeile, um die es sich handelt.

    this->Intro.Init(&CGame::Instance);
//Wichtige Zeile, um die es sich handelt.

//Wichtige Zeile, um die es sich handelt.

//Wichtige Zeile, um die es sich handelt.


    while (this->CurrentState() == 1)
    {
        if (this->MainWindow.GetEvent(this->Event))
        {
            if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::N))
            this->NextState();
            if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::P))
            this->PreviousState();
                
        }


        if (this->MainWindow.GetInput().IsKeyDown(sf::Key::Escape))
        {
            this->Running = false;
        }
        this->MainWindow.Draw(this->Text);
        this->MainWindow.Display();
        this->MainWindow.Clear();

    }

}


und Intro.h

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#ifndef _INTRO_h
#define _INTRO_h

#include "AllHeaders.h"

class CGame;

class CIntro
{
public:
    //InitMethode für IntroState

    void Init(CGame* Game);
    //CalculateMethode für Introstate

    void Calculate();
    //RenderMethode für Introstate

    void Render();
};

#endif


sowie Intro.cpp

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
#include "AllHeaders.h"



void CIntro::Init(CGame* Game)
{
    std::cout<<"Spielzustand: Intro\n";
    //

    Game->Text.SetText("Intro");
    //

}



Wie man sieht habe ich bisher versucht das ganze via übergebe einer Instanz von CGame zu übergeben. Leider hat es nicht geklappt.
Ich möchte das ganze noch einmal genauer erklären:

Ich möchte gerne, dass "CGame::CIntro" Funktionen verwenden kann, die CIntro inne hat. Aber leider muss sie auch CGame und seine Methoden benutzen muss. Ich möchte im grunde beide Klassen behandeln als ob es eine ist :D
Ich hoffe ich konnte es gut genug erklären und hoffe um Hilfe oder Anregungen zu diesem Problem.
Mein bisheriger Stand ist, dass ich das ganze mit dieser schon erwähnten Instanz versuche, aber leider bekomme ich folgenden Fehler:

Quellcode

1
2
1>.\Game.cpp(25) : error C2664: 'CIntro::Init': Konvertierung des Parameters 1 von 'CGame *(__cdecl *)(void)' in 'CGame *' nicht möglich
1>        Es gibt keinen Kontext, in dem diese Konvertierung möglich ist


MfG
Tarliotama

Das Gurke

Community-Fossil

Beiträge: 1 996

Wohnort: Pinneberg

Beruf: Schüler

  • Private Nachricht senden

2

27.09.2009, 19:23

Ich hab das jetzt nicht genau verstanden, aber das liest sich so, als ob du eine abstrakte Basisklasse für die Gamestates brauchst.

In dieser definierst du alles, was jedes Gamestate "können" muss und lässt sowohl das Intro also auch das Game davon erben.

3

27.09.2009, 19:45

Ich habe das mit den virtuellen Funktionen in der abstrakten Basisklasse schon alles anhand eines Tutorials durchgenommen.
Ich finde die Idee zwar genial wie das ganze umgesetzt war, aber "mein" Code war es letztendlich nicht.
Deshalb wollte ich die Sache mit den States gerne selber machen.
Leider scheitert es an dieser Instanz, die ich leider nicht erfolgreich übergeben bekomme.

Edit: Könnte man das mit dieser abstrakten Klasse auch so gestalten, das ich am Ende 2 "verschiedene" geerbte Klassen habe, die untereinander zusammen verwendet werden können und die unterschiedliche Methoden haben? (CGame hat bei mir nichts mit CIntro gemeinsam)

Das Gurke

Community-Fossil

Beiträge: 1 996

Wohnort: Pinneberg

Beruf: Schüler

  • Private Nachricht senden

4

27.09.2009, 19:50

Dein Edit ist doch das Ziel ;) In diesem Fall hätten CGame und CIntro dann halt gemeinsam, dass sie beide Gamestates sind, also von der Gamestate Klasse erben.

Natürlich dürfte CIntro immer noch eigene Methoden wie PlaybackVideo() oder was weiß ich verfügen. Nur kannst du auf diese Methoden dann vom GamestateManager nicht zugreifen. Der Manager weiß nämlich nur, dass er ein Gamestate vor sich hat und kümmert sich nicht drum welches.

xardias

Community-Fossil

Beiträge: 2 731

Wohnort: Santa Clara, CA

Beruf: Software Engineer

  • Private Nachricht senden

5

27.09.2009, 19:53

Hm..
Du hast zwei Klassen die nichts gemeinsam haben, und völligen Zugriff aufeinander haben sollen?

Warum brauchst du dann zwei Klassen, das klingt für mich nach einem Designfehler.

6

27.09.2009, 19:56

Erst einmal vielen Dank für die Hilfe :)

Ich denke ich werde das ganze nocheinmal mit einer abstrakten Klasse überarbeiten. Ich hoffe da kommen keine weiteren Probleme auf mich zu.
Noch eine Frage:

Müssen virtuelle Funktionen in der geerbten Klasse wieder auftauchen oder verschwinden diese automatisch wenn sie nicht überschrieben werden?

Und noch einmal vielen Dank

Edit: zu Xardias

Ursprüngliche wollte ich den Gamestatemanager in meinem Fall mit in die MainKlasse integrieren um mir 1 oder 2 Klassen zu sparen.
Ich dachte dies würde funktionieren und sich auszahlen, dem war aber leider nicht so :D

7

27.09.2009, 23:08

Zitat von »"Tarliotama"«


Müssen virtuelle Funktionen in der geerbten Klasse wieder auftauchen oder verschwinden diese automatisch wenn sie nicht überschrieben werden?

Weder noch.
Also: Du kannst die Funktion überladen oder du kannst es bleiben lassen. Aufgerufen werden kann die auf jeden Fall, wenn sie nicht überschrieben wurde, dann wird halt die Version der Basisklasse benutzt.
virtual besagt einfach nur, dass dynamisch die richtige Funktion rausgesucht wird. Wenn du also einen Zeiger auf ein Objekt hast und eine nicht virtuelle Funktion aufrufst wird immer die von dem Typ des Zeigers aufgerufen (ein Zeiger der vom Typ her ein Basisklassenzeiger ist, aber auf eine abgeleitete Klasse zeigt, würde also zu einem Aufruf von der Basisklassenfunktion führen, obwohl es ein Objekt der abgeleiteten Klasse ist).
Bei virtual wird immer auf den eigentlich Objekttyp geschaut, daher ist das ganze dynamsich (weil man dem Zeiger ja verschiedene Objekte von verschiedenen Klassen zuweisen kann), es entstehen aber auch minimale Mehrkosten. (Bei sehr kurzen und sehr oft benutzen Funktionen kann sich das auswirken).
Lieber dumm fragen, als dumm bleiben!

Werbeanzeige