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

19.02.2011, 18:12

C++ FunktionsArrays in Klassen

Hallo zusammen!

Ich versuche mich gerade an einem Raumladesystem meines Spiels.
Leider hänge ich seit einigen Tagen an einem Problem fest.
Aus den bisher gefundenen Treads bin ich leider nicht schlau geworden.

Ich habe 3 Klassen: CEnvironment, CRoomlist und CRoom0000.
CRoomlist soll eine Funktion von CRoom0000 in ein FunktionsZeigerArray von CEnvironment speichern.
Danach soll diese Funktion natürlich auch verwendet werden können (innerhalb CEnvironment).

Zur Erklärung hier ein grobes Ablaufschema:
CRoomlist->LoadRoom()
{ pCRoom0000 wird erstellt

pRenderRoom[0] wird mit der Funktion CRoom0000->Render() "gefüllt" }
CEnvironment->Render()
{ CEnvironment->pRenderRoom[0](); Wird ausgeführt }


Mein Hauptproblem ist, dass ich mit dem Syntax von Zeigern und Klassen immernoch Mühe habe.
Kommen noch Arrays und typedef hinzu, hab ich keine Ahnung mehr, wie ich es schreiben muss.

Hier mal der Code. Leider kann ich nichtmahl die Fehler beheben, die schon vor dem kompillieren auftauchen.

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
#include <TriBase.h> 
#include "Resource.h" 

class CRoom0000; 
typedef tbResult (CRoom0000::*pFuncTbResult)(); 
CEnvironment *pCEnvironment; 
CRoomlist     *pCRoomlist; 

class CRoom0000 
{ 
   public: 
   tbResult Render(){ return TB_OK; } 
} 

class CEnvironment 
{ 
   public: 
   pFuncTbResult   pRenderRoom[9]; 
   tbResult         Render() 
   { 
      pRenderRoom[0](); //Fehlermeldung: Error: Der Ausdruck muss einen (pointer-to-)Funktionstyp aufweisen. 
      return TB_OK; 
   } 
}; 

class CRoomlist 
{ 
   public: 
   CRoom0000 *pCRoom0000; 
   tbResult     LoadRoom() 
   { 
      pCRoom0000 = new CRoom0000; 
      pCEnvironment->pRenderRoom[0] = &CRoom0000::Render; //Fehlermeldung: <error-Type> *pCEnvironment | Error: Der Ausdruck muss den Typ "pointer-to-class" aufweisen. 
      return TB_OK; 
   } 
};


Ich würde mich freuen, wenn sich jemand den Code mal anschauen kann.

Vielen Dank für die Hilfe.
Sydon

Ps: Sorry für die schlechte Darstellung des Codes.

Bei mir funktioniert im Forum TabSpace leider nicht.

2

19.02.2011, 18:29

Müssen es den unbedingt Funktionszeiger sein?
Oder kann man es auch über abstrakte Basisklassen realisiern?

3

19.02.2011, 21:44

in zeile 33 in deinem code müsste das statt
&CRoom0000::Render
glaub ich
&CRoom0000->Render
heissen

mit den 2 doppelpunkten greift er ja normal auf statische methoden zu


und ich glaube das gleiche problem ist bei deinem typedef:
typedef tbResult (CRoom0000::*pFuncTbResult)();

wird zu:

typedef tbResult ( *(CRoom0000->pFuncTbResult) )(void);

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

4

19.02.2011, 22:01

ich jogge stimme zu.

du sagst ja selbst, dass dir die erfahrung fehlt. das spiegelt sich im code wieder.
Mein Hauptproblem ist, dass ich mit dem Syntax von Zeigern und Klassen immernoch Mühe habe.
Kommen noch Arrays und typedef hinzu, hab ich keine Ahnung mehr, wie ich es schreiben muss.

vielleicht ist die 3d programmierung noch nichts für dich?
schnapp dir dein nachschlagewerk und entwickel erstmal ein paar konsolenprogramme und 2d spiele.
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

5

20.02.2011, 01:10

Ich geh mal der Reihe nach^^ Aber Danke erstmal für die schnellen Antworten.

@Jogge
Ehrlich gesagt weis ich nicht ob das geht.
Ich muss zahlreiche Räume über ihre Nummer erstellen, Funktionen daraus aufrufen und wieder löschen können.
Diese Räume haben grösstteils verschiedene Funktionen, verschiedene MemberVariablen, etc.
Die einzige Lösung die ich bis jetzt kenne, ist die Funktionen der aktuellen Räumen zu speichern.

Aber das ist ja auch echt erfahrungssache. So wie ich in der Lehre als Hochbauzeichner immer wieder neue Zeichentechniken entwickelt hab, ist es halt auch beim Programmieren. Aber hätte ich es damals nicht auf solch merkwürdige weise gemacht, wäre ich heute ein schlechterer Zeichner. Und das schöne an digitalen Arbeiten ist ja, dass man alles löschen und anders machen kann.

@Skym0sh0
Leider klappt das auch nicht. Das Programm erwartet nun eine ) nach dem -> beim typedef.
Weil der typedef dann nicht funktioniert, bringt er im nachfolgenden Code natürlich jede Menge Fehler.

@Nacho Man
Also Probleme hab ich (in diesem Zusammenhang) nur mit dem Syntax von Zeigern in Verbindung mit Klassen. Ich hab nur grobe Ahnung, wann "." , "->" , "*" oder "::" zum Zuge kommt. Und da gibts mit steigender Anzahl an Elementen halt bald extrem viele Kombinationsmöglichkeiten.

Ob ich nun 2D oder 3D programmiere spielt keine Rolle. Irgendwo muss ich es auch lernen.


Ich versuche natürlich weiterhin Lösungen oder Beispiele im Internet zu finden.
Wenn aber jemand etwas findet bin ich überglücklich.

MfG Sydon

BurningWave

Alter Hase

Beiträge: 1 106

Wohnort: Filderstadt/Konstanz

Beruf: Student

  • Private Nachricht senden

6

20.02.2011, 01:26

Ich hab nur grobe Ahnung, wann "." , "->" , "*" oder "::" zum Zuge kommt.

Am Anfang ging es mir auch so, aber dann habe ich es mit der Zeit verstanden und eine Erfahrung gemacht: Man lernt es viel schneller, wenn man nicht herumprobiert, sondern eine Lösung findet und diese versteht.

Hier eine kurze Erklärung:
Mit dem Operator '.' kannst du auf Member von Objekten zugreifen (also z.B. MyObject.DoSomething();)
'->' bedeutet das gleiche, bis auf den Unterschied, dass du auf ein Objekt im Heap (z.B. zuvor mit new erstellt) zugreifst. Also:

C-/C++-Quelltext

1
2
3
4
CMyClass *pMyClass = new CMyClass; //Objekt auf dem Heap erzeugen (Zeiger mit *), pMyClass zeigt auf dieses Objekt)
pMyClass->DoSomething(); //ist das gleiche, wie (*pMyClass).DoSomething(); Der Indirektionsoperator '->' dereferenziert die Speicheradresse, die in pMyClass enthalten ist, zuerst. Das gleiche bewirkt (*pMyClass)
CMyClass::StaticMember(); //'::' greift hier auf eine statische Memberfunktion zu
delete pMyClass; //Löschen nicht vergessen!

Tobiking

1x Rätselkönig

  • Private Nachricht senden

7

20.02.2011, 01:33

Das :: ist schon richtig, aber es muss Klasse::Funktion sein. Objekte haben nämlich gar keine Funktionen sondern nur einen Zustand. Im Prinzip ist ein Aufruf wie "Objekt->Funktion();" nix anderes als ein Aufruf von "Funktion(Objekt* this);". Das ist auch der Grund warum es so nicht funktionieren wird wie du es vorhast.


Ehrlich gesagt weis ich nicht ob das geht.
Ich muss zahlreiche Räume über ihre Nummer erstellen, Funktionen daraus aufrufen und wieder löschen können.
Diese Räume haben grösstteils verschiedene Funktionen, verschiedene MemberVariablen, etc.
Die einzige Lösung die ich bis jetzt kenne, ist die Funktionen der aktuellen Räumen zu speichern.

Es kommt drauf an was für Funktionen du aufrufen willst. Wenn jeder Raum die gleiche Funktion (also bzgl. Name und Parameter) hat, die nur etwas anderes tut (wie z.B Render), dann ist das mit der Basisklasse genau das was du willst. Die Basisklasse sorgt dafür das jeder Raum diese Funktionen anbieten muss, und über einen Liste von Pointer auf die Basisklasse kannst du diese Funktionen für die einzelnen Räume aufrufen.

Wenn nicht, müsste man schon sehr tief in die Trickkiste greifen und sowas wie das composite Pattern wählen. Ich bezweifel aber das du das benötigst und wirklich willst.

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

8

20.02.2011, 01:45

'->' bedeutet das gleiche, bis auf den Unterschied, dass du auf ein Objekt im Heap (z.B. zuvor mit new erstellt) zugreifst. Also:

achso...

C-/C++-Quelltext

1
2
3
myclass object;
myclass *objectpointer = &object;
objectpointer->dosomething();

liegt object jetzt plötzlich auf dem heap? oO

mit dem -> operator sparst du dir das manuelle dereferenzieren von zeigern. gäbe es das nicht müsste man (*objectpointer).dosomething(); schreiben. steht in jedem gutem einführenden buch zu c++ und in jedem nachschlagewerk(eine unglückliche bezeichnung. will man möglichst guten code produzieren arbeitet man eins komplett durch).
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »NachoMan« (20.02.2011, 02:02)


9

20.02.2011, 02:05

Also indem ich Klassenprototypen hinzugefügt habe (bei "class CRoom0000" auch noch das Selbe mit den andern Klassen) meldet das Programm nur noch 1 Fehler. Und zwar der beim Aufrufen der Funktion in CEnvironment.

Der aktuelle Code ist also mit dem im Anfangsposting (fast) identisch.

@Tobiking
Ich werde mir das mit den Basisklassen mal genauer anschauen.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Sydon« (20.02.2011, 10:36)


dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

10

20.02.2011, 10:38

Nun, da dein pRenderRoom[0] ja ein Pointer auf eine Memberfunktion ist brauchst du natürlich ein Objekt vom Typ CRoom0000 um diese aufzurufen:

C-/C++-Quelltext

1
2
(object.*pRenderRoom[0])();
(pobject->*pRenderRoom[0])();

Werbeanzeige