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

13.07.2011, 02:20

[Delegates] Zeiger auf beliebige Klassen

Moin,

ich habe ein Eventsystem, das Delegates benutzt, um Events zu verarbeiten.
Es soll eine Basisklasse UserInterface geben und mehrere Unterklassen, z.b. MainInterface. Eine Methode von MainInterface könnte dann z.b. so heißen: AppliedSettings
Interfaces sind für mich nichts anderes als eine Ansammlung von Steuerelementen - normalerweise entspricht der Inhalt eines fensters einem Interface, aber man kann das natürlich noch weiter aufteilen und Interfaces können auch andere Interfaces enthalten. (Frame ftw.!)

Mein Problem ist jetzt, dass ich eine Liste von Delegates habe, die an einem Event lauschen. Diese Delegates müssen nicht zwingend dasselbe Interface besitzen und können somit Instanzen verschiedener Klassen sein. Das beißt sich mit der Idee der Liste. ^^

Delegate.h:

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
#ifndef DELEGATE_H
#define DELEGATE_H

namespace SF{
    namespace Core{

    template <typename T, typename R, typename P> class Delegate{
        T &obj;
        typedef R (T::*ptr)(P);
        ptr callback;

    public:

        Delegate(T &obj, ptr callback): obj(obj), callback(callback) {}

        R operator()(P p){
            return (obj.*callback)(p);
        }


    };

    }
}

#endif


MainInterface.h

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#ifndef MAIN_INTERFACE_H
#define MAIN_INTERFACE_H


#include "UserInterface.h"
#include "Event.h"
#include "MsgBox.h"

class MainInterface: public SF::GUI::UserInterface{


public:
    bool test(SF::GUI::Event evt){
        std::shared_ptr<SF::GUI::MsgBox> meineBox = SF::Core::EnvFactory::createMsgBox(std::wstring(L"Es funktioniert!!!"));
        return true;
    }

};


#endif


Auszug aus EventDispatcher.h:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
class EventDispatcher{

    public:
        typedef SF::Core::Delegate<SF::GUI::UserInterface, bool, Event> Callback;

    protected:

        typedef std::list<Callback> ClientsContainer;



Das Problem besteht also eigentlich darin, wie ich Objekte unterschiedlichen Typs in einem Standardcontainer untergebracht & verarbeitet bekomme. Das mit unterschiedlichen Typen ist aber eigentlich nicht relevant, da die Delegates zum Standardcontainer hin alle gleich aussehen (wenn ich z.b. nen Pointer auf das Objekt nehmen würde). Nur intern im Delegate spielen die unterschiedlichen Typen eigentlich eine Rolle. Problematisch ist hier die obige Verwendung von Templates, weil sie die Typinformation nach außen zum Standardcontainer herausträgt. (was ja eigentlich nicht nötig wäre).


Ich weiß, dass es mit Boost möglich ist, einen Standarcontainer mit Objekten unterschiedlicher Typen zu füllen. Aber eigentlich suche ich mehr nach einer Lösung, die Klasse nach außen zu verstecken und nur intern im Delegate zu unterscheiden. Ich frage hier, weil mir dazu genau nix einfällt.


Mit freundlichen Grüßen,


dispy

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

13.07.2011, 07:03

Mach es anders und führe für gemeinsame Elemente (was sie ja scheinbar sind) auch ein gemeinsames Interface ein.
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

3

13.07.2011, 09:44

Ich weiß, dass es mit Boost möglich ist, einen Standarcontainer mit Objekten unterschiedlicher Typen zu füllen. Aber eigentlich suche ich mehr nach einer Lösung, die Klasse nach außen zu verstecken und nur intern im Delegate zu unterscheiden. Ich frage hier, weil mir dazu genau nix einfällt.

Wie BlueCobold schon gesagt hat: Leit alle deine Delegates von einer gemeinsamen Basis ab:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
template <typename R, typenamt P>
class EventListener
{
public:
  virtual R operator()(P) = 0;
};

template <typename T, typename R, typename P>
class Delegate : public EventListener<R, P>
{
  ...
};


Abgesehen davon würd ich mir aber mal überlegen ob ich wirklich eine zentrale Stelle für sämtliche Listener haben will. Nicht jeden interessieren alle Events, warum sollen also die die sich nur für Tastatureingaben interessieren trotzdem auch sonst immer aufgerufen werden!?

4

13.07.2011, 13:03

So einfach kanns sein. Danke jungs ;)

Ich habe einen EventHandler, der schlüsselt die Events nach einer Kombination aus Fenster und Event auf. Dann leitet er die Events an den für das Fenster registrierten EventDispatcher weiter. Dieser wiederum hat eine Liste der Callbacks (später sollen die noch mit Prioritäten und Blocking-mechanismen ausgerüstet werden), die er abarbeitet.

Wenn man ein Event registriert, macht man das beim EventHandler - der kümmert sich um die Erzeugung und beim Unregister auch um die Zerstörung des Dispatchers.


MfG
dispy

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »dispy« (13.07.2011, 13:26)


Werbeanzeige