Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Le classi astratte fungono da espressioni di concetti generali da cui è possibile derivare classi più specifiche. Non è possibile creare un oggetto di un tipo di classe astratta. Tuttavia, è possibile usare puntatori e riferimenti ai tipi di classe astratti.
Si crea una classe astratta dichiarando almeno una funzione membro virtuale pura. Si tratta di una funzione virtuale dichiarata usando la sintassi dell'identificatore puro (= 0
). Le classi derivate dalla classe astratta devono implementare la funzione virtuale pura o sono anch'esse classi astratte.
Si consideri l'esempio presentato in Funzioni virtuali. Lo scopo della classe Account
è di fornire la funzionalità generale, ma gli oggetti di tipo Account
sono troppo generici per essere utili. Ciò significa Account
che è un buon candidato per una classe astratta:
// deriv_AbstractClasses.cpp
// compile with: /LD
class Account {
public:
Account( double d ); // Constructor.
virtual double GetBalance(); // Obtain balance.
virtual void PrintBalance() = 0; // Pure virtual function.
private:
double _balance;
};
L'unica differenza tra questa dichiarazione e la precedente è che PrintBalance
è dichiarato con l'identificatore pure (= 0
).
Limitazioni alle classi astratte
Le classi astratte non possono essere usate per:
Variabili o dati dei membri
Tipi di argomento
Tipi restituiti di funzione
Tipi di conversioni esplicite
Se il costruttore per una classe astratta chiama una funzione virtuale pura, direttamente o indirettamente, il risultato non è definito. Tuttavia, i costruttori e i distruttori per le classi astratte possono chiamare altre funzioni membro.
Funzioni virtuali pure definite
Le funzioni virtuali pure nelle classi astratte possono essere definite o hanno un'implementazione. È possibile chiamare tali funzioni solo usando la sintassi completa:
abstract-class-name::function-name()
Le funzioni virtuali pure definite sono utili quando si progettano gerarchie di classi le cui classi di base includono distruttori virtuali puri. Ciò è dovuto al fatto che i distruttori della classe base vengono sempre chiamati durante la distruzione degli oggetti. Si consideri l'esempio seguente:
// deriv_RestrictionsOnUsingAbstractClasses.cpp
// Declare an abstract base class with a pure virtual destructor.
// It's the simplest possible abstract class.
class base
{
public:
base() {}
// To define the virtual destructor outside the class:
virtual ~base() = 0;
// Microsoft-specific extension to define it inline:
// virtual ~base() = 0 {};
};
base::~base() {} // required if not using Microsoft extension
class derived : public base
{
public:
derived() {}
~derived() {}
};
int main()
{
derived aDerived; // destructor called when it goes out of scope
}
L'esempio mostra come un'estensione del compilatore Microsoft consente di aggiungere una definizione inline a un oggetto virtuale ~base()
puro. È anche possibile definirlo all'esterno della classe usando base::~base() {}
.
Quando l'oggetto aDerived
esce dall'ambito, viene chiamato il distruttore per la classe derived
. Il compilatore genera codice per chiamare in modo implicito il distruttore per la classe base
dopo il derived
distruttore. L'implementazione vuota per la funzione ~base
virtuale pura garantisce che per la funzione esista almeno un'implementazione. Senza di esso, il linker genera un errore di simbolo esterno non risolto per la chiamata implicita.
Nota
Nell'esempio precedente, la funzione virtuale pure base::~base
viene chiamata in modo implicito da derived::~derived
. È anche possibile chiamare in modo esplicito funzioni virtuali pure usando un nome completo di funzione membro. Tali funzioni devono avere un'implementazione o la chiamata genera un errore in fase di collegamento.