7 Stimmen

Auflösung überladener virtueller Funktionsaufrufe

Bitte beachten Sie den folgenden Code:

class Abase{};  
class A1:public Abase{};  
class A2:public A1{};  
//etc  

class Bbase{  
public:  
    virtual void f(Abase* a);  
    virtual void f(A1* a);  
    virtual void f(A2* a);  
};

class B1:public Bbase{  
public:
    void f(A1* a);  
};

class B2:public Bbase{  
public:
    void f(A2* a);
};  

int main(){  
    A1* a1=new A1();  
    A2* a2=new A2();  
    Bbase* b1=new B1();  
    Bbase* b2=new B2();  
    b1->f(a1); // calls B1::f(A1*), ok  
    b2->f(a2); // calls B2::f(A2*), ok  
    b2->f(a1); // calls Bbase::f(A1*), ok  
    b1->f(a2); // calls Bbase::f(A2*), no- want B1::f(A1*)! 
}  

Mich würde interessieren, warum C++ den Funktionsaufruf in der letzten Zeile durch Upcasting der this Zeiger des Objekts auf die Basisklasse, anstatt das Argument von f() ? Gibt es eine Möglichkeit, wie ich das gewünschte Verhalten erreichen kann?

10voto

Mark Ransom Punkte 283960

Die Wahl, welche Version von f aufzurufen, wird durch die Betrachtung der Kompilierzeit Typ des Parameters. Der Laufzeittyp wird bei dieser Namensauflösung nicht berücksichtigt. Da b1 ist vom Typ Bbase* alle von Bbase Mitglieder berücksichtigt werden; derjenige, der eine A2* ist die beste Übereinstimmung, also wird diese aufgerufen.

2voto

AnT Punkte 300728

"...entscheidet sich dafür, den Funktionsaufruf in der letzten Zeile aufzulösen, indem er den this-Zeiger des Objekts auf die Basisklasse upcastet..." . Wovon sprechen Sie? In allen Ihren Aufrufen ist der Typ des Objektzeigers Bbase * und die Funktionen, die die Aufrufe auflösen, gehören entweder zu Bbase oder seine Nachkommen. Der Compiler führt niemals ein Upcasting durch, um Ihre Aufrufe aufzulösen. Tatsächlich erfordern die ersten beiden Aufrufe Abwurf um den richtigen Overrider aufzurufen, da der Overrider zu der Klasse gehört, die sich weiter unten in der Hierarchie befindet. Was die letzten beiden Aufrufe betrifft - sie werden in die Bbase Klasse durch einen Zeiger der Bbase * Typ. Die Typen stimmen genau überein, es findet keinerlei Casting statt.

Was die Überladungsauflösung betrifft... Die Auflösung von Überladungen ist ein Prozess zur Kompilierzeit, der auf den statischen Typen der Argumente und den Reihen der möglichen Konvertierungen basiert. Sie haben ein Argument von A2 * Typ. Die Website f(A2 *) der Kandidat passte zu Ihrem Argument genau . El f(A1 *) Kandidat erfordert eine zusätzliche Umwandlung von A2 * a A1 * . Der Kandidat, der genau übereinstimmt, wird als der bessere angesehen und gewinnt die Überlastungslösung. Einfach.

1voto

Janick Bernet Punkte 19324
b1->f(static_cast<A1*>(a2));

Dies sollte den Compiler dazu zwingen, die Überladungsmethode mit dem Parameter vom Typ A1 zu verwenden.

0voto

Alexandre C. Punkte 53706

Das nennt man "Namen verstecken". Jedes f, das Sie in einer abgeleiteten Klasse deklarieren, überschattet jedes mögliche f in einer ihrer Basisklassen.

Verwenden Sie einen Cast auf die Basisklasse, um das gewünschte Verhalten zu erhalten.

Wenn Sie eine virtuelle Funktion überschreiben, überschreiben Sie nicht die überladenen Funktionen mit demselben Namen. Es handelt sich um unterschiedliche Funktionen (und um unterschiedliche Einträge in der vtable).

0voto

Florianx Punkte 321

Deine Überladungen in Bbase für Abase und A2 sind in B1 versteckt. Vielleicht können Sie dieses Problem so umgehen:

class Bbase{  
public:
    inline void f(Abase* a) { f_(a); }
    inline void f(A1* a) { f_(a); } 
    inline void f(A2* a) { f_(a); } 
protected:
    virtual void f_(Abase* a);  
    virtual void f_(A1* a);  
    virtual void f_(A2* a);  
};

class B1:public Bbase{  
protected:
    void f_(A1* a);  
};

class B2:public Bbase{  
protected:
    void f_(A2* a);
}; 

oder mit einer Vorlage in Bbase:

class Bbase{  
public:
    template<class myA>
    inline void f(myA* a) { f_(a); }
protected:
    virtual void f_(Abase* a);  
    virtual void f_(A1* a);  
    virtual void f_(A2* a);  
};

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X