2010-08-31 13 views
7

Sto estendendo una classe fornita da una libreria di terze parti. La classe, chiamiamola Foo, ha un metodo reset() che può essere richiamato per riavviare il comportamento di Foo. Il metodo reset() viene anche utilizzato internamente dalla classe.Applicazione dei metodi di terze parti virtualità

class Foo 
{ 
    public: 
    void reset() { 
     /* ... */ 
    } 
    void something() { 
     reset(); 
    } 
}; 

Finora, ho bisogno di sovraccaricare il metodo di reset() al fine di ripristinare le mie funzioni aggiuntive così:

class Bar : public Foo 
{ 
    public: 
    void reset() { 
     /* ...something... */ 
     Foo::reset(); 
    } 
}; 

Purtroppo, dal momento che il metodo Foo::reset() non è virtuale, chiamando Bar::something() ho la Metodo Foo::reset() chiamato anziché Bar::reset().

C'è un modo (diverso dal sovraccarico di Foo::something() per renderlo a ritroso-virtuale?

+0

A proposito, in questo modo ho imparato a impostare sempre come virtuale qualsiasi metodo che sia pubblico e utilizzato internamente. – Dacav

+1

Questa è una decisione sbagliata, Google per NVI e vedrai una tendenza ad evitare metodi virtuali pubblici. Il problema che stai affrontando è diverso: non puoi estendere una classe che non è stata progettata per essere estesa. –

+0

Suppongo fortemente le interfacce non virtuali. usare metodi virtuali 'virtuali' è come restituire gli handle ai tuoi interni -> è un No-No. –

risposta

5

Non è possibile estendere le classi che non erano destinate ad essere estese.

1

No, questo non è possibile. La virtualità di un metodo viene decisa quando il metodo viene dichiarato e non è possibile modificarlo successivamente in una classe base.

Per consentirvi di farlo, non vi è nulla di meno che un disastro. I metodi virtuali si comportano semplicemente in modo diverso rispetto ai metodi non virtuali e devono essere considerati durante la progettazione di un oggetto. Con questa proposta dovrei considerare che tutti i miei metodi potrebbero comportarsi in due modi nettamente diversi. Ciò aumenta in modo significativo il costo di progettazione dell'applicazione e riduce l'affidabilità.

1

Se nessuno dei reset o qualcosa di virtuale sono virtuali, sei fregato, e questa è la fine della storia. Se qualcosa è virtuale potresti sovrascriverlo. Tuttavia, se questi metodi necessari non sono virtuali, la classe non è intesa per essere estesa (o implementata correttamente, se previsto).

Edit:

Si potrebbe provare la composizione, per esempio

class Bar { 
    Foo f; 
    // foo's methods, etc, wrapped here 
    void something() { 
     f.reset(); 
     reset(); 
    } 
}; 

Ma se hai bisogno dell'intera conversione implicita, sei ancora imbottito.

3

Non è possibile rendere virtuale reset() nella libreria in modo tale da influire sulla classe base senza modificare il codice della classe base. Per i principianti, il compilatore non ha aggiunto il codice contabile necessario che consente di effettuare chiamate virtuali a reset().

2

Non esiste un modo "pulito" di farlo utilizzando l'ereditarietà. Virtual è una differenza di tempo di compilazione/collegamento: utilizzando un vtable per risolvere il metodo in fase di runtime (virtuale) rispetto al collegamento diretto (non virtuale).

Problemi correlati