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

Fred

Supermoderator

Beiträge: 2 121

Beruf: Softwareentwickler

  • Private Nachricht senden

21

10.12.2006, 17:00

Ich hätte auch mal eine wahrscheinlich blöde Frage aber:

Kann ich an eine Methode eine Variable aus der Klasse übergeben?

Beispiel:
Ich habe eine Klasse CPlayer. Sie enthüält verschiedene Informationen
wie Geschwindigkeit usw. Außerdem eine Funktuion Save(int information)
Dieser übergebe ich praktisch eine Information und sie speichert diese ab.
Wenn ich nun in der WinMain Funktion schreibe

C-/C++-Quelltext

1
g_pPlayer->Save(m_iSpeed)

dann sagt er mir die Variable ist nicht definiert. muss ich nun eine Neue
Funktion schreiben, welcher ich keine Variable übergebe und welche dann
wiederum die Savefunktion aufruft?


----------------------------------

Mir ist grad aufgefallen, dass das Problem doch anders zu sein scheint. Ich weiß nur nicht wo der Fehler liegt:
Ich habe eine Klasse CPlayer

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class CPlayer
{
public:
        int     m_iSpeed   // Geschwindigkeit

        int     m_iEnergy // Energie

        // Methoden

        int     Save(iInformation);
};

// Die Speicherfunktion

int             CPlayer::Save(iInformation)
{
        FILE*   stream;
    stream = fopen("Save\\Player.sav", "wb");
    fseek(stream, 0, SEEK_END);
    fprintf(stream,"%d", iInformation);
    fclose(stream); 
    return 1;
}


Nun die Mainfunktion
[cpp]
g_pPlayer->SavePlayer(g_pPlayer->m_iSpeed);
[cpp]

Kompilier ich das so kommt ein senden oder nicht senden Dialog.

22

10.12.2006, 21:16

hm ich glaub,wenn du sie public machst solte es gehen, wobei was ist so schlimm,die ganze klassenvariable zu übergeben und von dort aus dann auf die variable zuzugreifen? :)

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

23

10.12.2006, 21:35

@Fred: Da Save() eine Methoden von CPlayer ist, wieso übergibst du dann die Werte als Parameter und speicherst sie nich direkt aus Save()? Du könntest alternativ ein Assoziatives Array verwenden: std::map< int, int > z.B. oder besser boost::property_map. Dann kannst du irgendwelche IDs o.ä. als Parameter übergeben und dir die entsprechenden Eigenschaften aus dem Kontainer ziehen.

@koschka: Den Code solltest du nochmal überdenken, von wegen kleinen Verbesserungen wie Initialisierungsliste, kein Zuweisungsoperator in Konstruktoren, konstante Referenzen als Parameter, Prüfen auf Nullzeiger vor der Speicherfreigabe (is unsinnig) und vor allem der Selbstzuweisung im copy c'tor. Da wirst du nich glücklich mit!

grüße
@D13_Dreinig

grek40

Alter Hase

Beiträge: 1 491

Wohnort: Dresden

  • Private Nachricht senden

24

10.12.2006, 21:45

Zitat von »"Draculark"«


C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
// purpose :  - Save Gamestate

void Save() 
{ 
  //Variables

  CHero *Savegame = NULL;   // SaveClass

  Savegame = new CHero(Hero);

  cout << "Spielstand wird gespeichert." << endl; 
  ofstream Output ("Spielstand.sps" , ios::binary); 
  Output.write((char*) &Savegame, sizeof (Savegame)); 
  Output.close(); 
} // end Save


Jetzt beschäftige dich halt nochmal INTENSIV!! mit pointern usw.
Und schau für dein spezielles Problem nochmal nach, was fstream::write / read für Parameter brauch und was du für Parameter gibst.

koschka

Community-Fossil

Beiträge: 2 862

Wohnort: Dresden

Beruf: Student

  • Private Nachricht senden

25

10.12.2006, 21:48

ich hab das schon halb im Bett geschrieben, und wollte as auch so einfach wie mgl. machen - damit man es auch versteht, ohne Dinge wie Init. Listen, Selbstzuweisung etc. etc. . Ich weiss noch nichtmal ob der überhaupt zu compilieren geht ^^. Beei const. Referenzen haste aber Recht - is gefährlich.

Es diente nur zur Veranschaulichung der Überladung des operator=

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

26

10.12.2006, 21:51

Zitat von »"koschka"«

ich hab das schon halb im Bett geschrieben, und wollte as auch so einfach wie mgl. machen - damit man es auch versteht, ohne Dinge wie Init. Listen, Selbstzuweisung etc. etc. . Ich weiss noch nichtmal ob der überhaupt zu compilieren geht ^^. Beei const. Referenzen haste aber Recht - is gefährlich.

Es diente nur zur Veranschaulichung der Überladung des operator=


OK, halb im Bett kann man zählen lassen! ;) Aber erwähnen sollt man es ja trotzallem mal. :)
@D13_Dreinig

27

10.12.2006, 23:29

nc ich checks absolut ned :(

das sizeof hab ich jetzt ersetzt durch

C-/C++-Quelltext

1
sizeof(*Savegame)


das sollte jetzt eigentlich die richtige größe sein (laut tests ist die größe von sizeof(*Savegame) 404 und sonst nur 4, also das sollte jetzt stimmen.


char* hab ich in const char* umgewandelt(bleibt isch aber ja im prinzip gleich) und char* ist ein charpointer und einen pointer auf einen pointerzuweisen geht ja so, bzw nen pointer in nen anderen typ casten

C-/C++-Quelltext

1
(const char*) Savegame

wenns daran liegt, dann weiß ich ned was man anders machen kann, hab alle schreibvarianten durchprobiert:P

bei funktionen läuift das ja doch ähnlich ab?

C-/C++-Quelltext

1
2
3
4
5
6
7
8
void foo(int *pPointer);

int main()
{
  int *pNumber = NULL;
  *pNumber = 113;
  foo(pNumber);
//...


normale variablen müssten mit dem adressoperator "&" übergeben werden. also daran liegts irgendwie auch ned.

und warum funktionierts solange die konsole offen ist, nur nach dem beenden und neustarten auf einmal nicht mehr? das ergibt eben irgendwie keinen sinn^^

aber naja, werd mir übermorgen oder so mein büchlein wieder zurückholen und nochmal nachschauen, weil im google finde ich nichts passendes :/

mfg
Drac

koschka

Community-Fossil

Beiträge: 2 862

Wohnort: Dresden

Beruf: Student

  • Private Nachricht senden

28

11.12.2006, 00:10

Bitte korregiere mich wenn ich falsch liege, aber ich glaub du beziehst dich auf dies:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
// purpose :  - Save Gamestate

void Save()
{
  //Variables

  CHero *Savegame = NULL;    // SaveClass

  Savegame = new CHero(Hero);

  cout << "Spielstand wird gespeichert." << endl;
  ofstream Output ("Spielstand.sps" , ios::binary);
  Output.write((char*) &Savegame, sizeof (Savegame));
  Output.close();
} // end Save


In den Zeilen

C-/C++-Quelltext

1
2
  CHero *Savegame = NULL;    // SaveClass

  Savegame = new CHero(Hero);


Erstellst du einen Zeiger auf einen Hero, und weist ihm die Adresse 0 zu. In der nächste Zeile forderst du Speicher an.
Du rufst den Kopiekonstruktor auf (übergibst ihn das exestierende Objekt Hero).
Auch brauchst du den new Operator meistens nur für Arrays, die zur Laufzeit irgendwie dynamisch sein sollen, hier brauchst du es eigentlich nicht.
also kurz

C-/C++-Quelltext

1
  CHero Savegame(Hero);


Es wird eine Instanz der Klasse CHero erstellt, diese heisst Savegame und bekommt den "Eingabewert" Hero, als CopyConstruktor. (insofern Hero eine Instanz der Klasse CHero ist ;) )

mit new/delete so in etwa: (entspricht deinem oben nur mit expliziten Aufruf des = operators)

C-/C++-Quelltext

1
2
3
4
5
6
7
8
  CHero *Save=NULL;
  ....
  Save = new CHero;  //  Speicher anfordern

  Save = Hero;  // Zuweisungsopertor aufrufen

  ....
  // in Datei schreiben

  ....
  delete Save;


Wir müssten jetzt mal deinen Kopie- bzw. Zuweisungsoperator sehen, den ich vermute darin liegt das Problem.
Bzw. debugge mal im Zuweisungsooperator

Quellcode

1
sizeof(*Savegame)

stimmt, aber einfacher zu lesen wäre:

Quellcode

1
sizeof(CHero)

den Savegame ist ja nur ne Instanz der Klasse

29

11.12.2006, 10:02

also Hero ist ebenfalls ein pointer, nur nicht in der Variable extra mit nem p versehen, weil ich da erst später draufgekommen bin :)

C-/C++-Quelltext

1
2
// Global Variables

CHero *Hero;


C-/C++-Quelltext

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

// ///////////////////////             CHERO         ////////////////////////////

// //////////////////////////////////////////////////////////////////////////

// purpose :  - Copykonstructor of Class CHero

CHero::CHero(CHero *Hero)
{
  stName = Hero->stName;
  stRank = Hero->stRank;
  stOrt = Hero->stOrt;
  iLevel = Hero->iLevel;
  iExperience = Hero->iExperience;
  iRequiredExp = Hero->iRequiredExp;    
// Weitere Vriablen die so deklariert werden...     

}   // End Copy Konstructor


und zum new und delete :) also im buch wurde da ja später auch nur mehr mit new und delete gearbeitet zum speicherplatz reservieren und wieder freigeben, deswegen verwend ich das auch dauernd :)

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

30

11.12.2006, 10:19

In dem Fall macht es aber nicht wirklich Sinn das Objekt auf dem Heap abzulegen (es sei denn es handelt sich um viele Daten die den Stack unnötig belasten), es hat sogar Vorteile das Objekt auf dem Stack zu erstellen. Die Daten werden nämlich sicher wieder freigegeben, bei deiner Idee mit new ist das nicht der Fall.

Der copy c'tor sollte folgende Signatur haben:

C-/C++-Quelltext

1
2
CHero::CHero( const CHero& hero )
{}


Der sizeof Operator liefert übrigens keine korrekte Angabe über den verbrauchten Speicherplatz von CHero Objekten wenn diese C-Strings halten.

Ein Lösungsvorschlag:

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
class CHero
{
private:
    // Deine ganzen Membervariablen bla...


public:
    CHero()
    {}

    ~CHero()
    {}

    // etc...


    friend std::ostream& operator<<( std::ostream& lhs, const CHero& rhs )
    {
        // speichern der ganzen Daten

        lhs.write( ... )        
        lhs << xyz...

        return stream;
    }
};


Dann kannst du nämlich alle Heroobjekte per << Operator an jeden ostream übergeben, z.B.:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
int main( void ) 
{
    CHero foobar;

    std::ofstream out( "Herosave.xyz", std::ios::binary );
    out << foobar;
    out.close();
}


grüße
@D13_Dreinig

Werbeanzeige