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.11.2005, 14:07

Problem bei einer Übung...

Ich wollte zum Thema Klassen eine Übung schreiben. Die eigentliche Idee des Programms ist, dass zwei Einheiten erstellt werden, welchen ich befehlen kann, sich zu bewegen oder einander anzugreifen (Eigenltich kann nur den Spieler den Gegner angreifen). Aber erstmal der Quellcode:

Main.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
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
#include <iostream>
#include "Header.hpp"

using namespace std;


int main()
{
    //Spieler initialisieren

    CEinheiten Spieler(1000,70,20,0,0);
    CEinheiten Gegner(500,20,2,0,0);

    //Variable

    int Auswahl=0;

    //Menu

    do
    {
        cout<<"1 - Spieler anzeigen"<<endl;
        cout<<"2 - Angreifen"<<endl;
        cout<<"3 - Bewegen"<<endl;
        cout<<"4 - Beenden"<<endl;
        cout<<"Auswahl: ";
        cin>>Auswahl;

        //Menu verzweigen

        switch (Auswahl)
        {
            case (1):
            {
                cout<<"Spieler:"<<endl;
                Spieler.M_ZeigeDaten();

                cout<<endl<<endl;

                cout<<"Gegner:"<<endl;
                Gegner.M_ZeigeDaten();
            } break;

            case (2):
            {
                Spieler.M_Angreifen(&Gegner);
                cout<<"Angriff wurde aufgefuert"<<endl;
            } break;

            case (3):
            {
                Spieler.M_Bewegen();
                Gegner.M_Bewegen();
                cout<<"Bewegung wurde ausgefuehrt"<<endl;
            } break;
            
            case (4):
            {
                cout<<"Programm wurde beendet."<<endl;
            } break;

            default:
            {
                cout<<"Unglueltige Eingabe"<<endl;
            }
        }
    } while (Auswahl!=4);

    return 0;
}


CEinheiten.hpp:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class CEinheiten
{
    private:
        int m_Energie;
        int m_Angriff;
        int m_Geschwindigkeit;
        int m_xPos;
        int m_yPos;

    public:
        CEinheiten(int Energie, int Angriff, int Geschwindigkeit, int xPos, int yPos);
        void M_Angreifen(CEinheiten *pOpfer);
        void M_Bewegen();
        void M_ZeigeDaten();
};


CEinheiten.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
41
42
43
44
45
46
#include <iostream>
#include "Header.hpp"
using namespace std;


//Konstrukor

CEinheiten::CEinheiten(int Energie, int Angriff, int Geschwindigkeit, int xPos, int yPos)
{
    cout<<"Konstuktor wurde aufgerufen"<<endl;

    //Startwerte

    cout<<"m_Energie: "<<m_Energie<<endl; //Zur Kontrolle

    cout<<"Energie: "<<Energie<<endl; //Zur Kontrolle

    int m_Energie=Energie;
    cout<<"m_Energie: "<<m_Energie<<endl; //Zur Kontrolle

    int m_Angriff=Angriff;
    int m_Geschwindigkeit=Geschwindigkeit;
    int m_xPos=xPos;
    int m_yPos=yPos;

    cout<<endl<<endl;
}


void CEinheiten::M_Angreifen(CEinheiten *pOpfer)
{
    (*pOpfer).m_Energie-=m_Angriff;
}


void CEinheiten::M_Bewegen()
{
    m_xPos+=m_Geschwindigkeit;
    m_yPos+=m_Geschwindigkeit;
}


void CEinheiten::M_ZeigeDaten()
{
    cout<<"Alle Daten:"<<endl;
    cout<<"Energie: "<<m_Energie<<endl;
    cout<<"Angriff: "<<m_Angriff<<endl;
    cout<<"Geschw.: "<<m_Geschwindigkeit<<endl;
    cout<<"xPos   : "<<m_xPos<<endl;
    cout<<"yPos   : "<<m_yPos<<endl<<endl;
}


Irgendwie funktioniert der Konstruktor nicht richtig. Er wird zwar, wie ich an der cout-Ausgabe sehe, aufgerufen, und die Werte werden richtig gesetzt. Allerdings stimmen die Werte bei der Funktion M_ZeigeDaten nicht mehr. Sieht hier jemand den Fehler? :) Ich nicht... ;)

MfG P!Nh3aD

EDIT: Ich benutze Visual C++ von der beiliegenden CD von (C++für Spieleprogrammierer Auflage 2)

Lemming

Alter Hase

Beiträge: 550

Beruf: Schüler

  • Private Nachricht senden

2

27.11.2005, 14:16

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
//Konstrukor

CEinheiten::CEinheiten(int Energie, int Angriff, int Geschwindigkeit, int xPos, int yPos)
{
//...

    int m_Energie=Energie;// Das int musst du weglassen!

//...

    int m_Angriff=Angriff;
    int m_Geschwindigkeit=Geschwindigkeit;
    int m_xPos=xPos;
    int m_yPos=yPos;
//...

}

indem du int vor m_Energie und die anderen werte schreibst deklarierst du die hier als neue variablen...
einfach das int weglassen und es geht..

also so:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
//Konstrukor

CEinheiten::CEinheiten(int Energie, int Angriff, int Geschwindigkeit, int xPos, int yPos)
{
//...

    m_Energie=Energie;// Das int musst du weglassen!

//...

    m_Angriff=Angriff;
    m_Geschwindigkeit=Geschwindigkeit;
    m_xPos=xPos;
    m_yPos=yPos;
//...

}
Es gibt Probleme, die kann man nicht lösen.
Für alles andere gibt es C++...

Anonymous

unregistriert

3

27.11.2005, 14:22

1. Versuchs mal mit initialisierungslisten. Diese Zuweisung mit dem Zuweisungsoperator hat in Constructors nichts zu suchen.

2. Was spuckt der Debugger aus?

3. Frage am Rande: warum int? Einen Datentyp ohne fest definierte größe im Standard? Use long.

4. Schönheitsbedenken: Ein Objekt kann minimal 0 Power haben 0 = tot. daher: unsigned long und kein int. Denn unsigneds können nie tiefer als 0 gehen.

5. Schönheitsbedenken:

C-/C++-Quelltext

1
2
3
4
void CEinheiten::M_Angreifen(CEinheiten *pOpfer) 
{ 
    (*pOpfer).m_Energie-=m_Angriff; 
}
Kann gewaltig in die Hose gehen wenn man NULL oder ein nicht initialisiertes objekt übergibt. Außerdem wird nicht getestet ob das objekt schon power 0 hat oder überhaupt existiert.

6. Wofür M_ vor jeder Funktion?

7.

C-/C++-Quelltext

1
2
    int m_xPos=xPos; 
    int m_yPos=yPos;

Mal überlegen, wieso definierst du hier die variablen NEU? Wenn Du sie doch schon in der Klassedeklaration hast? Wundert es dich dann nicht das Du die Konzeptionelle Programmierung so elegant über den Haufen schmeißt wenn Du die Variablen lokal neu definierst?

4

27.11.2005, 15:00

Danke vielmals für eure Hilfe. Noch ein paar Fragen an nix da:
Zu 1. Ich habe erst gerade begonnen mit dem Lernen von C++, daher weiss ich leider noch nicht was Initialisierungslisten sind. :rolleyes:
Zu 2. Kenne ich auch noch nicht.
Zu 3. Ich verstehe die Frage nicht ganz.. long hat ja einen grösseren Werte-Bereich, und die Energie ist ja höchtens 1000 und kann nur sinken. Weshalb denn long nehmen? Wäre da nicht unsigned int besser?
Zu 4. Stimmt ;)
Zu 5. Das verstehe ich nicht ganz. Wie kann man denn ein nicht initialisiertes Objekt oder NULL übergeben? Könntest du mir das erklären?
Zu 6. Keine Ahnung, lasse ich von jetzt an weg.
Zu 7. Ja, jetzt ist es klar... :angel:

Anonymous

unregistriert

5

27.11.2005, 15:18

P!Nh3aD

1.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
class test
{
public: 
    test  (unsigned long power) : power_(power) {}
    ~test (void) {};

private:
    unsigned long power_;
};


2. Das steht nicht in den Buch? Kommt das noch? Erschreckend...

3. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccelng/htm/reftable_1.asp
Wie Du siehst ist int der einzigste Datentyp mit keiner Mindestgröße sondern Betriebssystemabhängig. Würdest Du jetzt z.B. dein Programm für ein NT System ausbauen und es dann auf einer 9x Plattform testen, kann es dort locker zu Undefinierten Verhalten kommen. Vorallem wenn es um das Binäre Speichern von Datentypen geht in Dateien und laden. Da knallt es oft.

Daher: long, int sollte man so oft wie möglich vermeiden wenn es um binäres Speichern geht. Von diesem Aspekt abgeleitet bezieht sich das auch auf das Programm.

4. hat sich geklärt

5.

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
    // Deine Funktion

void CEinheiten::M_Angreifen(CEinheiten *pOpfer) 
{ 
    (*pOpfer).m_Energie-=m_Angriff; 
}



// Aufruf der Funktion:

irgendeineEinheit.M_Angreifen (NULL); // Hier wird es kräftigst peng machen!




// Besser:

    // Deine Funktion

void CEinheiten::M_Angreifen(CEinheiten *pOpfer) 
{ 
    if (pOpfer != NULL)
        (*pOpfer).m_Energie-=m_Angriff; 
}


// Aufruf der Funktion:

irgendeineEinheit.M_Angreifen (NULL); // Passiert nichts


z1: Warum Denglisch?

z2: Mag zwar absolut trivial erscheinen, aber bei sowas tun mir die augen weh:

C-/C++-Quelltext

1
void M_ZeigeDaten();
Für mich sieht das aus wie ein Funktionsaufruf wenn der Parameter leer ist. Vorallem für Anfänger kann es hier oft zu Problemen kommen! Daher bei der Deklaration und Implementation:

C-/C++-Quelltext

1
void M_ZeigeDaten (void);


Vorallem: Hilft der lesbarkeit des Codes für Anfänger ;)

Werbeanzeige