[gelöst] ausgelagerte Klassenmethoden
-
Hallo,
ich habe schon einige Erfahrung mit delphi, und versuche mich jetzt bisschen in C++.in delphi kann man bei Klassen (bzw. deren Objekten) vom Hauptprogramm funktionszeiger hinterlegen. diese werden klassenintern aufgerufen, befinden sich aber nicht in der gleichen datei wie die klassendefinition. weiterhin wird bei diesen Methoden ein Instanzzeiger mitgeliefert.
gibt es sowas auch in C++? wenn ja, wie nennt sich das genau und wo finde ich sowas?
in delphi sieht das z.b. so aus:
Definition der klasse:
TNotify=procedure() of object; //typ des Funktionszeigers; of object besagt, dass bei der methode auch ein Pointer auf die Instanz übergeben wird class TBlah(TBlubb) private FNotify:TNotify; //variable für funktionszeiger procedure DoNotify; //klasseninterne Methode zum aufrufen der referenzierten funktion public property Notify:TNotify read FNotify write FNotify; //das property zum setzen des funktionszeigers end; procedure TBlah.DoNotify; begin if assigned(FNotify) then FNotify; //wenn funktionszeiger gesetzt ist, die Funktion aufrufen end;im Hauptprogramm erstellt man eine entsprechende methode und weist diese dem Objekt zu:
procedure BlahEvent(Sender:TObject);//hier plötzlich ein Parameter => Objekt-Referenz begin //mache irgendetwas end; //zuweisung des events myBlah.Notify=BlahEvent;jedesmal, wenn klassenintern DoNotify aufgerufen wird, wird die im Hauptprogramm befindliche BlahEvent-Methode mit ausgeführt.somit kann die Klassendefinition universeller verwendet werden.
wie würde das in C++ aussehen?
ich habe schon eine weile rumgesucht, auch funktionszeiger gefunden, aber da fehlt mir der instanz-zeiger. gut, man könnte diesen explizit mitgeben, aber evtl gibt es ja schon ein fertiges Konstrukt.
ich hoffe, ich habe das verständlich dargelegt.Gruß Frank
-
#include <iostream> using namespace std; typedef void (*funktionszeiger)(); struct bla { funktionszeiger funcptr; }; void funktion() { } int main() { bla B; B.funcptr = &funktion; }
-
wow, das ging ja schnell..
probiere das morgen gleich aus, danke schonmal
an den instanzpointer komme ich nicht so einfach ran (also innerhalb der funktion), oder?
Gruß Frank
-
ich habe heute mal so überlegt...vielleicht ist meine Herangehensweise falsch.
bin diesbezüglich von delphi geprägt.eventuell sollte ich die Event-Methoden in der Basis-Klasse nur protected oder sogar abstrakt machen (wenn das in C geht) und in der Main-Unit eine Ableitung erstellen, wo ich die Methoden mit Code fülle...
vielleicht auch ganz anders

Gruß Frank
-
WTF hast du denn vor?

And WTH ist eine Main-Unit?
aber zumindest kommt mir protected und ableiten sehr bekannt vor

-
ich habe mir eine Klasse (bzw. mehrere) geschrieben, um das Erstellen eines stinknormalen windows-fensters (und Unterkomponenten) zu kapseln. Für diverse "Ereignisse", sei es WM_Create,WM_Paint,... möchte ich halt gerne im Hauptprogramm (Main-Unit = Quelldatei mit der Nachrichtenschleife = main.cxx) Code ausführen.
z.b. sollen in der Haupt-Quellcode-Datei die verschiedenen Klassen (bzw. deren Objekte) zusammengebracht werden.um mal ein direktes Beispiel zu bringen...
ich habe ein Treeview,
dort drin Items,
beim Doppelklick auf ein Item soll eine Funktion im Hauptprogramm ausgeführt werden. welches das aktuelle TreeItem auslesen muss. diese Routine muss also wissen, von welchem "Fenster" (in dem Fall das Treeview, könnten ja z.b. auch mehrere sein) das Event kommt, um das markierte Item auszulesen und mit dessen Daten die Funktion (z.b. anderes Programm aufrufen) aufruft.ich möchte den Code (was soll beim doppelklick gemacht werden) ungern in die Basisklasse einbauen, um diese universell zu halten.
habe meinen bisherigen Code mal hier hochgeladen.
In der tree.cxx/.h habe ich die Event-Methoden schon vorbereitet (DoXxxx).Gruß Frank
-
Wie wärs wenn du globale funktionen verwendest?
Die deklarierst du irgendwo und im header machst du ein
extern <protyp der funktion>
zB
extern void tu_was_bei_doppelclick();dann bindest du den header in treeview.cxx ein und führst
tu_was_bei_doppelclick();
(in Callback funktion oder keine Ahnung wie WinAPI tickt) aus.
-
Der Vorschlag mit dem Callback gefällt mir nicht so ganz, da ich versuche das in OOP zu realisieren.wie man erkennen kann, hab ich sogar die API-Callback nur auf einen Wrapper innerhalb meiner Klasse umgebogen, um möglichst viel Code in der Klasse selbst zu haben.
ich habe versucht das mit der Überschreib-Variante zu realisieren, leider wird die überschreibende Methode nicht aufgerufen. unter delphi ist dies (nach dem direkten Zuweisen eines Methodenzeigers) die gängige Methode um Events mit eigenem Code zu hinterlegen, ohne in die Basisklassen-Definition einzugreifen.
die Ursprungsmethode wird aufgerufen.ich hab die aktuelle Variante mal hier hochgeladen: http://www.filedropper.com/first
Ich kann mir nicht vorstellen, dass es unter C++ keine Möglichkeit gibt, dieses für mein Verständnis so simple Problem auf OOP-Ebene zu lösen.
Gruß Frank
-
frank schrieb:
Der Vorschlag mit dem Callback gefällt mir nicht so ganz, da ich versuche das in OOP zu realisieren.
Du willst ein callback also verwende auch eins. OOP hat nichts mit klassen und methoden zu tun.
schau dir das event handling von boost::signal mal an. Ansonsten gibts noch das event handling von java swing. es gibt viele möglichkeiten und du musst nur daran denken _was_ du tun willst und nicht _wie_. denn das _wie_ diktiert deine plattform.
-
Observerpattern heißen die "OOP-Callbacks"
-
frank schrieb:
gibt es sowas auch in C++? wenn ja, wie nennt sich das genau und wo finde ich sowas?
Objektgebundene Methodenzeiger gibt es in C++ nicht, zumindest nicht als Sprachfeature. Als Alternative sieh dir boost::signal<>, wie von Shade vorgeschlagen, oder std::tr1::function<> an. Wenn es in der Effizienz einigermaßen in der Nähe der Methodenzeiger von Delphi sein soll, gäbe es noch die Fast Delegates.
Shade Of Mine schrieb:
Ansonsten gibts noch das event handling von java swing.
... das sich aber in C++ mangels anonymer Klassen nicht eben anbietet.
-
ich habe die OnDblClick-Methode in der basis-klasse einfach nur als virtual deklariert und schon kann ich sie so überschreiben, wie ich das will. die Methode in der Abgeleiteten Klasse wird durch die Wndproc der Basisklasse ordnungsgemäß aufgerufen.
Danke trotzdem für die Antworten.Gruß Frank