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

Fawkes

Frischling

  • »Fawkes« ist der Autor dieses Themas

Beiträge: 58

Beruf: Realschüler :)

  • Private Nachricht senden

1

09.11.2013, 15:01

Funktion als Parameter übergeben?

Hallo, ich suche eine möglichkeit eine Funktion einer Klasse in einer anderen Funktion zu übergeben. Ich haben folgenden Code:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
int playAnimation( int EngineFps, int spriteFps, void (*class::playAnimation)() ){ // <- hier soll die Funktion playAnimation übergeben werden. Dabei soll die Klasse //keine Rolle spielen

        for( int i = 0; i < spriteFps; i++ ){
            
            if( i == spriteFps ){
                (*this.*playAnimation)(); // <- Hier komm ich nicht weiter
            }
        }


Tjap und das ist das Problem :). Hat hier jemand eine Idee?

FSA

Community-Fossil

  • Private Nachricht senden

2

09.11.2013, 15:10

Ich weiß nicht ganz genau was es dir bringen soll, aber deklariere deine zu übergebende Methode als static. Als Paramater deiner playAnimation wäre so etwas wohl richtiger:

C-/C++-Quelltext

1
2
int playAnim(..., void (*function)())
{}

Zitat

Der RCCSWU (RandomCamelCaseSomtimesWithUndersquare) Stil bricht auch mal mit den veraltet strukturierten Denkmustern und erlaubt dem Entwickler seine Kreativität zu entfalten.

Cranberry

Treue Seele

Beiträge: 312

Wohnort: Innsbruck, Tirol

  • Private Nachricht senden

3

09.11.2013, 15:17

Warum musst du eine Funktion als Parameter übergeben?
Die Lösung von FSA ist richtig aber ich glaube in diesem Fall sollte man (falls ich dein Vorhaben richtig verstanden habe(was eher nicht der Fall ist)) die Instanz des Objekts das die Funktion playAnimation hat übergeben.
z.B.:

C-/C++-Quelltext

1
int playAnimation(Sprite* sprite){  sprite->playAnimation();}


Etwas mehr Quellcode wäre nützlich.


P.S.: Warum ist playAnimation vom Typ int? Was wird zurückgegeben?

H5::

Treue Seele

Beiträge: 368

Wohnort: Kiel

  • Private Nachricht senden

4

09.11.2013, 15:21

Eine Funktion oder Methode? Funktionen recht einfach Mit Funktionzeigern, bei Methoden etwas schwieriger (wenn nicht statisch). Hast du dir mal Lambda Funktionen angesehen und dem Stichwort Closure?

Lambda Functions in C++11
Programs as Data: Function Pointers
:love: := Go;

FSA

Community-Fossil

  • Private Nachricht senden

5

09.11.2013, 15:23

Ich verstehe auch nicht, warum eine globale Funktion, eine Funktion innerhalb eine Klasse mit einem Funktionszeiger aufrufen sollte. ?(

Zitat

Der RCCSWU (RandomCamelCaseSomtimesWithUndersquare) Stil bricht auch mal mit den veraltet strukturierten Denkmustern und erlaubt dem Entwickler seine Kreativität zu entfalten.

Fawkes

Frischling

  • »Fawkes« ist der Autor dieses Themas

Beiträge: 58

Beruf: Realschüler :)

  • Private Nachricht senden

6

09.11.2013, 15:29

Ich mache das, da ich mit Sfml arbeite und ich den Sprites keine eigene Fps geben kann, sondern nur dem Fenster(60) ich will aber bei meinen Sprite animationen eine andere Fps haben. Das ganze steht in einem namespace namens Engine.

C-/C++-Quelltext

1
Engine::PlayAnim( int windowFps/*60 in dem Fall*/, int spriteFps/*Das Sprite soll z.B alle 8 Bilder gezeichnet werden*/, und jetzt die animationFunc von dem Object.)


Ich hoffe man hat das so verstanden. ^^

Die Animation Function:

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
void Player::animation(){

if( kmove == IDLE ){
if( theFighter == Fighter1 ){
PlayFighter1Idle();
}
}

if( kmove == RUN ){
if( theFighter == Fighter1 ){
PlayFighter1Run();
}
}

if( kmove == JUMP ){
if( theFighter == Fighter1 ){
PlayFighter1Jump();
}
}

if( kmove == FALLBACK ){
if( theFighter == Fighter1 ){
PlayFighter1Fallback();
}
}
}

Legend

Alter Hase

Beiträge: 731

Beruf: Softwareentwickler

  • Private Nachricht senden

7

09.11.2013, 15:32

Meistens regelt man sowas besser über Interfaces. Das einzige was mir einfallen würden, waren Callbacks, die macht man vielleicht mal so. Dann will man sich wohl das hier ansehen http://de.cppreference.com/w/cpp/utility/functional/function. Aber bitte so wenig möglich, also wenn wirklich nötig.
"Wir müssen uns auf unsere Kernkompetenzen konzentrieren!" - "Juhu, wir machen eine Farm auf!"

Netzwerkbibliothek von mir, C#, LGPL: https://sourceforge.net/projects/statetransmitt/

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

8

09.11.2013, 15:39

Im C++ geht das leider nicht ganz so einfach bzw. gibt es mehrere nicht ganz optimale Lösungsmöglichkeiten.
Wenn die Übergabemethode statisch sein könnte, wobei ich hier nicht davon ausgehen, wäre wie von FSA vorgeschlagen, eine statische Methode eine sehr einfache Lösung.
Vorschläge:
  1. Eine Lösung wäre es, daraus ein Funktions-Template zu machen und den Klassentyp des Callbackparamters als Template-Parameter zu übergeben.

    C-/C++-Quelltext

    1
    2
    3
    4
    5
    6
    
    template<typename T> int playAnimation(int EngineFps, int spriteFps, T& callbackObj, void (*T::callbackFunc)())
    {
        [...]
        callbackObj.*callbackFunc();
        [...]
    }

    Etwas unschön daran ist, dass die Methode wie alle Templates im Header stehen muss. Längere Methoden können also zu längerer Übersetzungszeit und mehrfacher Template-Instanzierung führen.


  2. Eine etwas unschöne aber relativ einfache Lösung die ggf. auch Probleme mit Zugriffsmodifikatoren in der Klasse, in der die Callback-Methode steckt, verursachen kann, wäre es die Klasseinstanz einfach als void-Zeiger zu übergeben:

    C-/C++-Quelltext

    1
    2
    3
    4
    5
    6
    
    int playAnimation(int EngineFps, int spriteFps, void* const callbackObj, void (*callbackFunc)(void* const callbackObj))
    {
        [...]
        callbackFunc(callbackObj);
        [...]
    }

    In der Callback-Funktion muss man dann nur den void-Zeiger mit einen reinterpret_cast wieder in seinen Klassentyp konvertieren.


  3. Die von mir empfohlene Lösung weil sie am universalsten funktioniert und ggf. auch statische oder virtuelle Funktionen als Callback verwendet werden können, ist es, eine eine "Delegate"-Klasse einzusetzen.
    Die gibt es zb. in der STL als "function" im "functional"-Header, in Boost oder in anderen Bibliotheken. (sigslot, CodeProject - Fastest possible C++ Delegates)

    Das könnte dann zum Beispiel so aussehen:

    C-/C++-Quelltext

    1
    2
    3
    4
    5
    6
    7
    8
    
    #include <functional>
    [...]
    int playAnimation(int EngineFps, int spriteFps, const std::function<void()>& callback)
    {
        [...]
        callback();
        [...]
    }

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Spiele Programmierer« (09.11.2013, 16:51)


Fawkes

Frischling

  • »Fawkes« ist der Autor dieses Themas

Beiträge: 58

Beruf: Realschüler :)

  • Private Nachricht senden

9

09.11.2013, 15:53

Die Lösungen von Spieleprogrammierer sind klasse, ich werde die erste Variante benutzen, da meine Funktion nicht sonderlich groß oder kompliziert ist. Danke dafür ;)

10

10.11.2013, 02:17

bind ist auch klasse:
http://en.cppreference.com/w/cpp/utility/functional/bind

Wenn du ein std::function benutzt oder deine Funktion, der du eine andere Funktion übergeben möchtest, ein Template ist, kannst du auf der Aufruferseite dann sowohl bind, als auch lambdas benutzen, was eine sehr hübsche und saubere Lösung ist. Setzt natürlich einen Halbwegs aktuellen Compiler voraus.
Lieber dumm fragen, als dumm bleiben!

Werbeanzeige