Frage

Ich möchte die Basisklasse Implementierung einer virtuellen Funktion aufrufen, ein Mitglied Funktionszeiger verwendet wird.

class Base {
public:
    virtual void func() { cout << "base" << endl; }
};

class Derived: public Base {
public:
    void func() { cout << "derived" << endl; }

    void callFunc()
    {
        void (Base::*fp)() = &Base::func;
        (this->*fp)(); // Derived::func will be called.
                       // In my application I store the pointer for later use,  
                       // so I can't simply do Base::func().
    }
};

In dem obigen Code der abgeleiteten Klasse Implementierung von func wird von callfunc aufgerufen werden. Gibt es eine Möglichkeit ich ein Mitglied Funktionszeiger speichern, die Fußpunkte :: func, oder muss ich using in irgendeiner Weise zu benutzen?

In meiner eigentlichen Anwendung verwende ich boost :: bind ein boost :: Funktionsobjekt in callfunc zu schaffen, die ich später func aus einem anderen Teil meines Programms nennen verwenden. Also, wenn boost :: bind oder boost :: Funktion eine Möglichkeit hat, um dieses Problem zu bekommen, die auch helfen würden.

War es hilfreich?

Lösung

Wenn Sie eine virtuelle Methode über eine Referenz nennen oder einen Zeiger Sie immer den virtuellen Call Mechanismus zu aktivieren, die am meisten abgeleiteten Typen findet.

Ihre beste Wette ist eine alternative Funktion hinzuzufügen, die nicht virtuell ist.

Andere Tipps

Was Sie versuchen, leider zu tun ist, nicht möglich. Pointer-to-Mitglied-Funktionen sind entwickelt die virtualness der Funktion aufrechtzuerhalten darauf zu.

Ihr Problem ist, dass ein Mitglied Funktionszeiger nicht ganz als bloßer Funktionszeiger gleich ist. Es ist eigentlich nicht nur ein Zeiger, sondern ein wesentlich komplexere Struktur , die auf der Ebene des Compilers Implementierung in seinen Einzelheiten variiert. Wenn Sie es über die Syntax aufrufen (this->*fp)() Sie es tatsächlich auf das ursprüngliche Objekt aufrufen, die Versendung virtuelle Funktion verursacht.

Eine Sache, die funktionieren kann, ist es zu einem nicht-Methode Zeigertyp zu werfen. Dies ist ein wenig knarrende, aber ich denken sollte es funktionieren. Sie müssen noch eine Base * passieren, aber sie tun es explizit und die virtuelle Funktion Dispatch umgangen wird:

typedef void BasePointer(Base*);

void callFunc()
{
    BasePointer fp = (BasePointer *)&Base::func;
    fp(this);
}

Update: Ok, nein, man kann es auf diese Weise nicht tun. Es ist illegal, und wäre es nicht sicher sein, wenn es legal ist. Die C ++ FAQ hat mehr zu diesem . Aber das wissen nicht lösen Ihr Problem. Das Problem ist, dass, Zeiger-zu-Objekt oder Zeiger-to-Mitglied, wenn Sie Base::func durch einen Base Zeiger, um das Objekt es zeigt muss auch sein ein Base anrufen möchten. Wenn Sie das arrangieren können, dann können Sie ein Mitglied Funktionszeiger verwenden.

Hier ist ein weiterer Gedanke, nicht schön, aber zumindest praktikabel. Geben Sie eine Funktion in Derived, nicht-virtuellen, Anrufe, die explizit Base::func. Zeigen Sie auf diese Stelle. Es wird nicht skaliert, wenn Sie dies im allgemeinen Fall von vielen verschiedenen Varianten von func und callFunc tun müssen, aber es wird für ein Verfahren gut funktionieren.

Gibt es einen bestimmten Grund für diese Zeiger über eine Funktion zu tun?

Es soll möglich sein, nur schreiben:

Base::func();

, um die Basisklassenimplementierung nennen.

Zusätzlich zu dem, was Quark sagt, eine allgemeine Bemerkung ist, dass Sie ein Signal / Slot-Implementierung verwenden sollen eher als ein bloßer Funktionszeiger. Boost hat man, gibt es libsigc und ein paar andere.

Was ist los mit diesem?

(Base(*this).*fp)();

Nun, wenn Sie damit zufrieden sind, dann stellt sich die Frage, warum Sie auch einen Funktionszeiger in erster Linie verwendet wird. Ich denke, einige mehr Kontext könnte helfen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top