2016-01-13 10 views
6

Ecco la definizione della classe:In C++, questo metodo chiama associazione statica o associazione dinamica?

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() { ... } 
... }; 

E qui è il codice del client:

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

Un libro che stavo leggendo detto l'ultima affermazione è statica vincolante:

enter image description here

Tuttavia, la frase sembra ancora vincolante dinamicamente perché rect->draw deve essere chiamata da Puntatore nella "vtable" di rect in fase di esecuzione.

Qualcuno ha idee sul fatto che lo rect->draw sia un collegamento statico o un collegamento dinamico?

risposta

8

Rect::draw() non è final e rect è un puntatore, quindi utilizza l'associazione dinamica.

Ma il compilatore può utilizzare la de-virtualizzazione come ottimizzazione se tutte le variabili sono in ambito locale e tutti i tipi sono noti.

+0

'final' gli impediva di compilare. Vieta l'override piuttosto che fermarlo. –

+0

@DmitryRubanovich: Poiché il metodo 'final' non può essere sovrascritto (quindi non assumendo' Square :: draw'), come ottimizzazione, il compilatore può chiamare il metodo 'final' senza usare * vtable *. – Jarod42

+0

il compilatore non chiama nulla. Genera il codice che (metaforicamente) effettua le chiamate. Un compilatore non può generare il codice in una sottoclasse che sovrascrive un metodo 'final' in una super classe. Un compilatore deve generare un errore in fase di compilazione se incontra tale codice. Generare codice che ignorerebbe la virtualità di una funzione significherebbe infrangere la dichiarazione. In altre parole, non sarebbe un'ottimizzazione del compilatore. Sarebbe un bug del compilatore. –

1

La comprensione generale del vtable è corretta.

Penso che quello che il libro sta cercando di dire è che il compilatore potrebbe, e generalmente lo farà, ottimizzare il progetto rect-> per essere chiamato senza andare al vtable.

In questo caso, il compilatore può vedere che il rect sta puntando a un oggetto Rectangle.

Nella maggior parte dei codici di produzione, raramente si verifica il caso.

0

Dipende da dove. Al di fuori del codice della classe, questo sarà sempre un binding dinamico. Durante la costruzione di un oggetto (all'interno di uno qualsiasi dei costruttori fino alla catena di ereditarietà) la consultazione della tabella virtuale è sospesa perché gli oggetti di classe bambino potrebbero non essere stati ancora inizializzati.

Problemi correlati