- Incapsulamento ed estensibilità dei Tipi
- Ereditarietà
- Polimorfismo
- L' Overload
- Funzioni Virtuali
- I Membri Statici di una classe
- Templates di Funzioni
- Templates delle Classi
- Classi Astratte
Funzioni Virtuali
La parola chiave virtuale è l'identificatore di funzione, che fornisce un meccanismo per selezionare dinamicamente in fase di esecuzione un appropriato membro-di-funzione tra le funzioni delle classi di base e derivate. Le strutture non possono avere funzioni virtuali. Esse possono essere utilizzate per cambiare le dichiarazioni solo per i membri della funzione.
La funzione virtuale, come una funzione ordinaria, deve avere un corpo eseguibile. Quando viene chiamata, la sua semantica è la stessa di quella delle altre funzioni.
Una funzione virtuale può essere sottoposta a override in una classe derivata. La scelta di quale definizione di funzione dovrebbe essere chiamata per una funzione virtuale, è fatta in modo dinamico (in fase di esecuzione). Un caso tipico è quando una classe base contiene una funzione virtuale, e classi derivate hanno le loro versioni di questa funzione.
Il puntatore alla classe base può indicare sia un oggetto di classe base che l'oggetto di una classe derivata. La scelta del membro-funzione da chiamare verrà eseguita in fase di esecuzione e dipende dal tipo di oggetto, non dal tipo di puntatore. Se non vi sono membri di un tipo derivato, la funzione virtuale della classe base viene utilizzata per impostazione predefinita.
I Distruttori sono sempre virtuali, indipendentemente dal fatto che siano dichiarati o meno con la parola chiave virtual.
Prendiamo in considerazione l'uso di funzioni virtuali sull'esempio di MT5_Tetris.mq5. La classe base CTetrisShape con la funzione virtuale Dra è definita nel file include MT5_TetrisShape.mqh.
//+--------------------------------------------------------------------------------+
|
Inoltre, per ciascuna classe derivata, questa funzione è implementata in conformità con le caratteristiche di una classe discendente. Ad esempio, la prima forma CTetrisShape1 ha la propria implementazione della funzione Draw():
class CTetrisShape1 : public CTetrisShape
|
La forma Square è descritta dalla classe CTetrisShape6 ha la propria implementazione del metodo Draw():
class CTetrisShape6 : public CTetrisShape
|
A seconda della classe a cui appartiene l'oggetto creato, essa chiama la funzione virtuale di questa o quella classe derivata.
void CTetrisField::NewShape()
|
Modifier 'override' #
Il modificatore 'overrire' significa che la funzione dichiarata deve eseguire l'override("scavalco) del metodo di una classe genitore. L'utilizzo di questo metodo consente di evitare errori di primaria importanza, ad esempio, consente di evitare la modifica accidentale della firma del metodo. Supponiamo che, il metodo 'func' è definito nella classe base. Il metodo accetta una variabile int come argomento:
class CFoo |
In seguito, il metodo viene scavalcato nella classe figlia:
class CBar : public CFoo |
Tuttavia, il tipo di argomento è erroneamente cambiato da int a short. In realtà, questo non è l'overriding del metodo, ma è l'overloading del metodo. Agendo in accordo all algoritmo definente la funzione overloadata, Il compilatore può in alcune situazioni scegliere un metodo definito nella classe base invece del metodo overridato.
Al fine di evitare tali errori, si dovrebbe aggiungere in modo esplicito il modificatore 'override' per il metodo che si desidera overridare.
class CBar : public CFoo |
Se la firma del metodo viene modificata durante l'override, il compilatore non sarà in grado di trovare un metodo con la stessa firma nella classe padre, e restituituirà un errore di compilazione:
'CBar::func' medoto è dichiarato con lo specificatore 'override' ma non fa l'override di nessun metodo della classe base |
Modificatore 'final' #
Il modificatore 'final' fa il contrario — vieta il metodo prevalente alla classi figlie. Se un'implementazione metodo è sufficiente e completa del tutto, dichiarare questo metodo con il modificatore 'final' in modo da assicurarsi che non sarà modificato successivamente.
class CFoo |
Se si tenta di eseguire l'override un metodo con il modificatore 'final', come mostrato nell'esempio precedente, il compilatore restituirà un errore:
'CFoo::func' metodo dichiarato come 'final' non può essere overridato da 'CBar::func' |
Vedi anche