Frage zu Zeigern auf virtuelle Methoden
-
hallo Leute,
angenommen ich habe eine Klasse:
class foo { protected: void (foo::*)(void) m_pSomeMethod; virtual void SomeMethod(void) {} public: foo(void) : m_pSomeMethod(&foo::SomeMethod) {} };jetzt steht ja in m_pSomeMethod ein Zeiger auf die foo::SomeMethod.
so weit so gut.
angenommen, ich leite jetzt von dieser Klasse noch eine Klasse ab:class bar : public foo { protected: virtual void SomeMethod(void) { /* hier wird jetzt irgendwas gemacht */ } };kann ich davon ausgehen, dass wenn ich ein Object von bar instanziiere,
auch automatisch der Konstruktor von foo ausgeführt wird?
und befindet sich dann in dem vererbten m_pSomeMethod die Adresse
von foo::SomeMethod oder von bar::SomeMethod?schonmal danke im voraus
MfG DrakoXP
-
DrakoXP schrieb:
kann ich davon ausgehen, dass wenn ich ein Object von bar instanziiere,
auch automatisch der Konstruktor von foo ausgeführt wird?Ja.
und befindet sich dann in dem vererbten m_pSomeMethod die Adresse
von foo::SomeMethod oder von bar::SomeMethod?Weder noch, Zeiger auf Member sind keine Zeiger und enthalten auch keine Adressen. Ein Zeiger auf eine virtuelle Memberfunktion bezeichnet jeweils den letzten Overrider dieser Funktion für das Objekt, auf dass er angewendet wird - es findet also dynamische Bindung statt.
ist der dynamische Typ des Objekts x ein foo, so bezieht sich x.*m_pSomeMethodauf foo::SomeMethod - ist es ein bar, so bezeichet x.*m_pSomeMethod bar::SomeMethod
-
DrakoXP schrieb:
hallo Leute,
angenommen ich habe eine Klasse:
class foo { protected: void (foo::*)(void) m_pSomeMethod; virtual void SomeMethod(void) {} public: foo(void) : m_pSomeMethod(&foo::SomeMethod) {} };jetzt steht ja in m_pSomeMethod ein Zeiger auf die foo::SomeMethod.
so weit so gut.
angenommen, ich leite jetzt von dieser Klasse noch eine Klasse ab:class bar : public foo { protected: virtual void SomeMethod(void) { /* hier wird jetzt irgendwas gemacht */ } };kann ich davon ausgehen, dass wenn ich ein Object von bar instanziiere,
auch automatisch der Konstruktor von foo ausgeführt wird?
und befindet sich dann in dem vererbten m_pSomeMethod die Adresse
von foo::SomeMethod oder von bar::SomeMethod?schonmal danke im voraus
MfG DrakoXP
Die Konstruktion wirkt mehr als unsinnig, und ich frage mich wirklich wozu du den Zeiger auf die virtuelle Methode hälst.
Aber erstmal der einfache Teil:
Eine Klasse B die von einer Klasse A abgeleitet wird, ruft automatisch auch deren Konstruktor auf. Um genau zu sein wird dieser als aller erstes Initialisiert (Sprich: die Konstuktion läuft immer von der untersten Hierachie nach oben ab, daher sollte man auch niemals eine virtuelle Methode innerhalb eines Konstruktors aufrufen, da immer nur der bisher konstruierte Teil vorhanden ist). Du kannst den Konstruktor in der Initialisierungsliste beeinflussen sofern du nicht den Standardkonstruktor verwenden willst.
Nun zu virtuellen Funktionen:
Jede virtuelle Funktion wird in der vtable zum Objekt hinterlegt, dort wird auch die jeweils spezisierteste Form für den Aufruf verwendet (Sprich die von der konkreten Klasse, oder die erste Implementierung von dieser an in der Hierachie nach oben gegangen).
Du kannst aber auch die virtuelle Funktion der Basisklasse aufrufen:
class foo { protected: virtual void SomeMethod() { // ... } public: foo() {} }; class bar : public foo { protected: virtual void SomeMethod() { //... foo::SomeMethod(); // jetzt noch die Implementierung der Basisklasse aufrufen } };So, eine Antwort darauf was dein Zeiger veranstaltet kann ich dir aber nicht geben (ich gehe davon aus das die virtuelle Funktion von bar verwendet wird), da ich solch ein merkwürdiges Konstrukt noch nie gesehen habe. Was willst du mit diesem Zeiger überhaupt erreichen?
cu André
-
asc schrieb:
da ich solch ein merkwürdiges Konstrukt noch nie gesehen habe
Ich auch nicht.
void (foo::*m_pSomeMethod)(void) ;
-
Leute, was ihr so seltsam findet funktioniert tatsächlich

ich habe einen Wrapper geschrieben, eine Klasse namens window.
diese hat als member einen Objectswitch (siehe Magazin: http://www.c-plusplus.net/forum/viewtopic-var-t-is-149970.html)
als Key habe ich einen unsigned long, der die Window-Message darstellt
und als data eben einen
unsigned long (window::*)(unsigned long, unsigned long)wenn man nun auf z.B. WM_CREATE... reagieren möchte,
baut man eine Methode in seine Kindklasse von window ein,
die dem oben gezeigten Schema entspricht.
im Konstruktor der Kindklasse wird dann die Funktion dem ObjectSwitch hinzugefügt.Mein Problem ist jetzt:
ich habe noch eine button-Klassse geschrieben, die von window erbt.
in ihr sind eben solche Methoden vorhanden UND bereits im Konstruktor dem ObjectSwitch eingefügt worden.Die Frage:
wenn ich jetzt von button erbe, und eine seiner Methoden überlade,
wird dann automatisch die Überladene Methode verwendet,
oder muss ich erst die alte wieder aus dem ObjectSwitch entfernen und die überladene dann einfügen?MfG DrakoXP
/EDIT: ok, ich habe gerade den Beitrag von Camper gelesen und das beantwortet eigentlich schon meine Frage,
also thx