2016-01-13 6 views
6

Hier ist die Klassendefinition:In C++ heißt diese Methode statische Bindung oder dynamische Bindung?

class Shape { public: 
    virtual void draw() = 0; ... 
}; 
class Circle : public Shape { 
    public: 
     void draw() { ... } 
... }; 
class Rectangle : public Shape { public: 
    void draw() { ... } ... 
}; 
class Square : public Rectangle { 
    public: 
     void draw() { ... } 
... }; 

Und hier ist der Client-Code:

Square* sq = new Square; 
Rectangle* rect = new Rectangle; 
Shape* ptr_shape; 
ptr_shape = sq; 
ptr_shape->draw(); 
rect->draw(); 

Ein Buch, das ich lesen die letzte Anweisung sagte, war statisch ist verbindlich:

enter image description here

Allerdings sieht die Aussage immer noch dynamisch für mich aus, da rect->draw von th aufgerufen werden sollte Der Zeiger in der "vtable" von rect in der Laufzeit.

Hat jemand Ideen darüber, ob die rect->draw statische Bindung oder dynamische Bindung ist?

Antwort

8

Rect::draw() ist nicht final und rect ist ein Zeiger, so dass es dynamische Bindung verwendet.

Der Compiler kann jedoch die De-Virtualisierung als Optimierung verwenden, wenn alle Variablen im lokalen Geltungsbereich sind und alle Typen bekannt sind.

+0

'final' würde verhindern, dass es kompiliert wird. Es verbietet das Überschreiben, statt es zu stoppen. –

+0

@DmitryRubanovich: Da 'final' Methode nicht überschrieben werden kann (also keine' Square :: draw' vorausgesetzt wird), kann der Compiler als 'optimization' die 'final' Methode ohne die * vtable * aufrufen. – Jarod42

+0

der Compiler ruft nichts auf. Es erzeugt den Code, der (metaphorisch) die Anrufe macht. Ein Compiler kann den Code in einer Unterklasse nicht generieren, der eine "final" -Methode in einer Superklasse außer Kraft setzt. Ein Compiler muss einen Kompilierungsfehler generieren, wenn er auf einen solchen Code stößt. Einen Code zu generieren, der die Virtualität einer Funktion ignoriert, würde bedeuten, die Deklaration zu brechen. Mit anderen Worten, es wäre keine Compiler-Optimierung. Es wäre ein Compilerfehler. –

1

Sie sind insgesamt Verständnis für die Vtable ist korrekt.

Ich denke, was das Buch versucht zu sagen ist, dass der Compiler, und im Allgemeinen, wird das Rect-> Draw optimieren, um aufgerufen zu werden, ohne auf die Vtable zu gehen.

In diesem Fall kann der Compiler sehen, dass das Rect auf ein Rectangle-Objekt zeigt.

In den meisten Produktionscode wird dies selten der Fall sein.

0

Es hängt davon ab, wo. Außerhalb des Codes der Klasse ist dies immer eine dynamische Bindung. Während der Objekterstellung (innerhalb eines der Konstruktoren bis zur Kette der Vererbung) wird die virtuelle Tabellennachfrage unterbrochen, da untergeordnete Objekte möglicherweise noch nicht initialisiert wurden.