Classi Astratte e Funzioni Virtuali Pure

Le classi astratte vengono utilizzate per la creazione di entità generiche, che prevedi di utilizzare per creare classi derivate più specifiche. Una classe astratta può essere utilizzata solo come classe base per un'altra classe, motivo per cui è impossibile creare un oggetto del tipo di classe astratta.

Una classe che contiene almeno una pura funzione virtuale è astratta. Pertanto, le classi derivate dalla classe astratta devono implementare tutte le sue pure funzioni virtuali, altrimenti saranno anche classi astratte.

Una funzione virtuale viene dichiarata "pura" utilizzando la sintassi degli specificatori puri. Si consideri l'esempio della classe CAnimal, che viene creata solo per fornire funzioni comuni - gli oggetti del tipo CAnimal sono troppo generici per l'uso pratico. Quindi, CAnimal è un buon esempio per una classe astratta:

class CAnimal
  {
public:
                      CAnimal();     // Constructor
   virtual void       Sound() = 0;   // Una funzione virtuale pura
private:
   double             m_legs_count;  // Il numero di gambe dell'animale
  };

Qui Sound() è una pura funzione virtuale, perché è dichiarata con l'identificatore della funzione virtuale pura PURE (=0).

Le funzioni virtuali pure sono solo le funzioni virtuali per le quali è impostato lo specificatore PURE: (=NULL) o (=0). Esempio di dichiarazione di classe astratta e uso:

class CAnimal
  {
public:
   virtual void       Sound()=NULL;   // IL metodo PURE, dovrebbe essere sovrascritto nella classe derivata, CAnimal ora è astratta e non può essere creata
  };
//--- Derivato da una classe astratta
class CCat : public CAnimal
 {
public:
  virtual void        Sound() { Print("Myau"); } // PURE è sovrascritto, CCat non è astratto e può essere creato
 };
 
//--- Esempi di uso errato
new CAnimal;         // Errore di 'CAnimal' - il compilatore restituisce l'errore "impossibile istanziare la classe astratta"(cannot instantiate abstract class)
CAnimal some_animal; // Errore di 'CAnimal': il compilatore restituisce l'errore "impossibile istanziare la classe astratta"
 
//--- Esempi di uso corretto
new CCat;// Nessun errore: la classe CCat non è astratta
CCat cat;// Nessun errore: la classe CCat non è astratta

 
Restrizioni su classi astratte

Se il costruttore di una classe astratta chiama una funzione virtuale pura (direttamente o indirettamente), il risultato non è definito.

//+------------------------------------------------------------------+
//| Una classe base astratta                                         |
//+------------------------------------------------------------------+
class CAnimal
  {
public:
   //--- Una funzione virtuale pura
   virtual void      Sound(void)=NULL;
   //--- Funzione
   void              CallSound(void) { Sound(); }
   //--- Costruttore
   CAnimal()
    {
     //--- Una chiamata esplicita del metodo virtuale
     Sound();
     //--- Una chiamata implicita (utilizzando una terza funzione)
     CallSound();
     //--- Un costruttore e/o un distruttore chiama sempre le sue funzioni,
     //--- anche se sono virtuali e sovrascritti da una funzione chiamata in una classe derivata
     //--- Se la funzione chiamata è virtuale pura
     //--- la sua chiamata causerà un errore critico di runtime: "pura chiamata di funzione virtuale"
    }
  };

Tuttavia, costruttori e distruttori per le classi astratte possono chiamare altri membri di funzione.