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

cojo2015

Alter Hase

  • »cojo2015« ist der Autor dieses Themas

Beiträge: 516

Wohnort: bei mir zu Hause

Beruf: Schüler

  • Private Nachricht senden

1

20.08.2015, 11:32

[C++] In Memberfunktion auf Membervariablen aus einer anderen Klasse zugreifen

Hallo Leute,

zurzeit programmiere ich im 2-er Team ein Spiel. Im Hauptmenü gibt es drei Buttons: Starten, Optionen, Beenden. Wenn man auf "Optionen" klickt, dann soll man entscheide können, ob zb die FPS im Spiel angezeigt werden sollen, oder nicht (Das umstellen von true oder false klappt soweit). Dieses Optionsmenü ist einen eigene Klasse, welche von einer akstrakten Klasse erbt (die Klasse "MainMenu" erbt ebenfalls):
Options.hpp

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
#pragma once

#include "gamestate\include\GameState.hpp"
#include "gamestate\states\include\MainMenuState.hpp"

class GameState;

class Options : public GameState
{
public:
    Options();
    ~Options();

    void Update(sf::Time deltatime, Game &game) override;
    void ProcessEvents(Game &game) override;
    void Render(sf::RenderWindow &App) override;

public:
    bool m_bPlayMusic, m_bShowFPS;
    bool m_bClicked;

    float m_fMusicVolume;

private:
    sf::Texture Background_Texture;
    sf::Sprite  Background_Sprite;

    sf::Text txtPlayMusic;
    sf::Text txtShowFPS;
    sf::Text txtMusicVolume_static;
    sf::Text txtMusicVolume_variable;
    sf::Text txtPageUP_PageDOWN;

    sf::Font font;

private:
    void loadBackground();
    void setTextes();

};


Um auf die "FPS-Variable" zugreifen zu können, erstelle ich in der Game.hpp eine Instanz dieser Klasse: (Zeile 64)

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
#pragma once

#include <SFML\Graphics.hpp>
#include <memory>
#include <iostream>

#include "gamestate\include\GameState.hpp"

class GameState;
class MainMenuState;
class PlayState;
class LevelOneState;
class Options;

class Game
{
public:
    enum class gameStates{MAINMENU, PLAY, OPTIONS, LEVELONE};

    Game();
    ~Game();

    void Run(); // Run kümmert sich um den Ablauf und dem Erhalt des Spieles

    void changeState(gameStates newState);

    // operator für sf::RenderWindow, damit man es auch in andere Klassen benutzen kann
    sf::RenderWindow& operator[] (int index)
    {
        switch (index)
        {
        case 0:
            return App;
            break;

        default:
            break;
        }
    }

public:
    sf::RenderWindow App;

private:
    void Update(sf::Time deltatime);
    void HandleEvents();
    void Render();

    void UpdateStatistics(sf::Time elapsedTime);

private:
    static const sf::Time TimePerFrame;

    bool m_bPause;

    // statics
    sf::Font                mFont;
    sf::Text                mStatisticsText;
    sf::Time                mStatisticsUpdateTime;
    std::size_t             mStatisticsNumFrame;

    std::unique_ptr<GameState> CurrentState;

    Options options; // Hier wird die Instanz erstellt!
};


Hier der entsprechende Codeausschnitt in der Game.cpp (wo abgefragt werden soll, ob die FPS angezeigt werden sollen):

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    if (options.m_bShowFPS == true)
    {
        if (mStatisticsUpdateTime >= sf::seconds(1.0f))
        {
            mStatisticsText.setString(
                "Frames / Second = " + std::to_string(mStatisticsNumFrame) + "\n" +
                "Time / Update = " + std::to_string(mStatisticsUpdateTime.asMicroseconds() / mStatisticsNumFrame) + "us");

            mStatisticsText.setColor(sf::Color::Red);

            mStatisticsUpdateTime -= sf::seconds(1.0f);
            mStatisticsNumFrame = 0;
        }
    }


Jetzt bekomme ich folgende Fehlermeldungen:
error C2079: 'Game::options' verwendet undefiniertes class 'Options'
error C2079: 'Game::options' verwendet undefiniertes class 'Options'
error C2079: 'Game::options' verwendet undefiniertes class 'Options'
error C2079: 'Game::options' verwendet undefiniertes class 'Options'
error C2079: 'Game::options' verwendet undefiniertes class 'Options'
error C2079: 'Game::options' verwendet undefiniertes class 'Options'
error C2228: Links von ".m_bShowFPS" muss sich eine Klasse/Struktur/Union befinden.

Welche(n) Fehler habe ich gemacht? Danke im Voraus :)

buggypixels

Treue Seele

Beiträge: 125

Wohnort: Meerbusch

Beruf: Programmierer

  • Private Nachricht senden

2

20.08.2015, 12:19

In der Game.cpp ein include "Options.h"

Tobiking

1x Rätselkönig

  • Private Nachricht senden

3

20.08.2015, 12:20

Für das was du mit Options machst, reicht keine forward declaration mehr. Du musst da schon die komplette Deklaration includieren.

cojo2015

Alter Hase

  • »cojo2015« ist der Autor dieses Themas

Beiträge: 516

Wohnort: bei mir zu Hause

Beruf: Schüler

  • Private Nachricht senden

4

20.08.2015, 12:24

In der Game.cpp ein include "Options.h"
Das hatte ich schon gemacht :) (Hätte ich vllt erwähnen sollen)

5

20.08.2015, 20:10

Als erstes würde ich dir empfehlen, nicht die Operatoren zu überladen, statt dessen get-Methoden zu nutzen. Macht den Code besser Lesbar.
Dann bist du nicht Konsequent in der Benamung der Membervariablen (das nur am Rande).

Zitat

In Memberfunktion auf Membervariablen aus einer anderen Klasse zugreifen


Auch hier empfielt es sich set/get-Methoden zu nutzen.

Wenn du in der Klasse Game, Option nicht als Referenz oder Pointer nutzt reicht, die Vorwärtsdeklaration nicht aus, du must den den Header includieren von Options in Game.h.
Wer aufhört besser werden zu wollen hört auf gut zu sein!

aktuelles Projekt:Rickety Racquet

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

6

20.08.2015, 21:31

Wenn du mich fragst, ist das Grundproblem hier, dass keine klare Trennung zwischen Logik und Darstellung herrscht. Du hast ein State Object, das nicht nur Zustand hält und die Logik für den Umgang mit diesem Zustand definiert, sondern auch noch die Darstellung der Daten sowie die dazu nötigen Ressourcen verwaltet. Gleichzeitig hast du ein Game Object, das ebenfalls Ressourcen für die Darstellung verwaltet, sich aber auch um Logik kümmert...

Wieso muss von außen auf die Fenster zugegriffen werden und was genau ist der Grund, wieso dies am besten über einen operator [] erfolgen sollte? Von get/set Methoden ist grundsätzlich abzuraten, die sind in der Regel Anzeichen dafür, dass man sich im Design wo den Weg verbaut hat. Besser den Grundriss fixen, als Löcher in Wände bohren...

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

7

20.08.2015, 22:30

Was in diesem Fall natürlich Käse ist, dot, weil er ja eine Klasse Options hat, die nichts weiter tun soll als Settings-Variablen zu halten und bereitzustellen. Das ist nichts weiter als stupide Datenhaltung. Natürlich ist dort der Zugriff auf Member direkt sinnvoll.
Statt aber auch mal in einem Topic einen konkreten Hinweis zu geben, was er eigentlich ändern soll, bringst Du immer wieder dieselben Sprüche. Wie wär's denn mal zur Abwechslung, wenn Du eine konkrete Lösung anbieten würdest?

Über SRP kann man viel und breit reden, dennoch wird er immer beim Rendering wissen wollen, ob er die FPS anzeigen soll oder nicht und welche Option in den Settings genau drin steht.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

8

20.08.2015, 23:01

Was in diesem Fall natürlich Käse ist, dot, weil er ja eine Klasse Options hat, die nichts weiter tun soll als Settings-Variablen zu halten und bereitzustellen.

Aus irgendeinem Grund hat diese Klasse aber auch Sprites, Texturen, Fonts und eine Render-Methode...

Das ist nichts weiter als stupide Datenhaltung.

Exakt, d.h. diese Klasse Options ist also vermutlich keine so tolle Klasse, vermutlich sollte man das besser anders machen...

Natürlich ist dort der Zugriff auf Member direkt sinnvoll.

Nope. Sinnvoll wäre es, eine separate Klasse rein für das Settings GUI zu haben, welches dann, z.B. über einen Mediator, beim entsprechenden anderen Objekt, welches sich um die Darstellung der FPS kümmert, die showFPS() bzw. hideFPS() Methoden aufruft...

Statt aber auch mal in einem Topic einen konkreten Hinweis zu geben, was er eigentlich ändern soll, bringst Du immer wieder dieselben Sprüche. Wie wär's denn mal zur Abwechslung, wenn Du eine konkrete Lösung anbieten würdest?

Ich versuche in der Regel, erstmal die Probleme aufzuzeigen und dem Fragesteller die Chance zu geben, selbst über Lösungen nachzudenken, ohne ihn mit einem konkreten Lösungsvorschlag in einen gedanklichen Tunnel zu locken...

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »dot« (21.08.2015, 02:22)


BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

9

21.08.2015, 06:34

Aus irgendeinem Grund hat diese Klasse aber auch Sprites, Texturen, Fonts und eine Render-Methode...
Richtig, aber das war gar nicht Teil der Fragestellung des Topics.

Nope. Sinnvoll wäre es, eine separate Klasse rein für das Settings GUI zu haben, welches dann, z.B. über einen Mediator, beim entsprechenden anderen Objekt, welches sich um die Darstellung der FPS kümmert, die showFPS() bzw. hideFPS() Methoden aufruft...
Was allerdings voraussetzt, dass diese Komponente zu diesem Zeitpunkt überhaupt existiert, was sehr fragwürdig und vermutlich gar nicht der Fall ist. Außerdem frage ich mich, wo diese Info also geladen und gespeichert werden soll, wenn es keine Klasse geben sollte, die diese Informationen persistieren und laden kann. Diese wäre effektiv ja nur ein Datencontainer. Ob man den Zugriff da über definierte Indices macht oder über direkte Member, das ist dabei ja erstmal egal und hängt auch vom verwendeten Serialisierungs- oder Persistierungsframework ab. Wie genau würdest Du ohne so eine Klasse oder so ein Framework denn die Information dauerhaft speichern?
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von »BlueCobold« (21.08.2015, 06:53)


cojo2015

Alter Hase

  • »cojo2015« ist der Autor dieses Themas

Beiträge: 516

Wohnort: bei mir zu Hause

Beruf: Schüler

  • Private Nachricht senden

10

21.08.2015, 07:09

Aus irgendeinem Grund hat diese Klasse aber auch Sprites, Texturen, Fonts und eine Render-Methode...
Richtig, weil ich in der Options-Klasse auch Text darstellen will und (später) ein Hintergrund hinzufügen möchte.

Außerdem frage ich mich, wo diese Info also geladen und gespeichert werden soll
Währe es an dieser Stelle sinnvoll den fstream (#include <fstream>) zu verwenden, also die Variablen in einer Datei zu speichern?

Werbeanzeige