Share via


Funzioni virtuali

Una funzione virtuale è una funzione membro che si prevede sia ridefinito nelle classi derivate.Quando si fa riferimento a un oggetto classe derivata utilizzando un puntatore o un riferimento alla classe di base, è possibile chiamare una funzione virtuale per tale oggetto ed eseguire la versione derivata della classe di funzione.

Le funzioni virtuali assicurare che la funzione venga chiamata corretta per un oggetto, indipendentemente dall'espressione utilizzata per effettuare la chiamata di funzione.

Si supponga che una classe base contenga una funzione dichiarata come virtuale e una classe derivata definisce la stessa funzione.La funzione dalla classe derivata viene richiamata per gli oggetti della classe derivata, anche se la chiamata viene eseguita tramite un puntatore o un riferimento alla classe di base.Nell'esempio seguente viene illustrata una classe base che fornisce un'implementazione di PrintBalance funzione e due classi derivate

// deriv_VirtualFunctions.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;

class Account {
public:
   Account( double d ) { _balance = d; }
   virtual double GetBalance() { return _balance; }
   virtual void PrintBalance() { cerr << "Error. Balance not available for base type." << endl; }
private:
    double _balance;
};

class CheckingAccount : public Account {
public:
   CheckingAccount(double d) : Account(d) {}
   void PrintBalance() { cout << "Checking account balance: " << GetBalance() << endl; }
};

class SavingsAccount : public Account {
public:
   SavingsAccount(double d) : Account(d) {}
   void PrintBalance() { cout << "Savings account balance: " << GetBalance(); }
};

int main() {
   // Create objects of type CheckingAccount and SavingsAccount.
   CheckingAccount *pChecking = new CheckingAccount( 100.00 ) ;
   SavingsAccount  *pSavings  = new SavingsAccount( 1000.00 );

   // Call PrintBalance using a pointer to Account.
   Account *pAccount = pChecking;
   pAccount->PrintBalance();

   // Call PrintBalance using a pointer to Account.
   pAccount = pSavings;
   pAccount->PrintBalance();   
}

Nel codice precedente, le chiamate a PrintBalance sono identiche, ad eccezione dell'oggetto pAccount punti su.Poiché PrintBalance è virtuale, la versione della funzione definita per ogni oggetto viene chiamata.PrintBalance funzione nelle classi derivate CheckingAccount e SavingsAccount “override„ la funzione nella classe di base Account.

Se la classe è dichiarata che non fornisce un'implementazione di override di PrintBalance funzione, l'implementazione predefinita della classe base Account viene utilizzato.

Le funzioni delle classi derivate eseguono l'override delle funzioni virtuali nelle classi di base solo se il tipo è lo stesso.Una funzione in una classe derivata non può essere diversa da una funzione virtuale in una classe base nel tipo restituito solo; l'elenco di argomenti necessario differire anche.

Nel chiamare una funzione utilizzando i puntatori o riferimenti, è necessario rispettare le seguenti regole:

  • Una chiamata a una funzione virtuale viene risolta in base al tipo sottostante di oggetto per il quale viene chiamato.

  • Una chiamata a una funzione non virtuale viene risolta in base al tipo di puntatore o un riferimento.

Nell'esempio seguente viene illustrato come funzioni virtuali e non virtuali si comportano una volta chiamato tramite puntatori:

// deriv_VirtualFunctions2.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;

class Base {
public:
   virtual void NameOf();   // Virtual function.
   void InvokingClass();   // Nonvirtual function.
};

// Implement the two functions.
void Base::NameOf() {
   cout << "Base::NameOf\n";
}

void Base::InvokingClass() {
   cout << "Invoked by Base\n";
}

class Derived : public Base {
public:
   void NameOf();   // Virtual function.
   void InvokingClass();   // Nonvirtual function.
};

// Implement the two functions.
void Derived::NameOf() {
   cout << "Derived::NameOf\n";
}

void Derived::InvokingClass() {
   cout << "Invoked by Derived\n";
}

int main() {
   // Declare an object of type Derived.
   Derived aDerived;

   // Declare two pointers, one of type Derived * and the other
   //  of type Base *, and initialize them to point to aDerived.
   Derived *pDerived = &aDerived;
   Base    *pBase    = &aDerived;

   // Call the functions.
   pBase->NameOf();           // Call virtual function.
   pBase->InvokingClass();    // Call nonvirtual function.
   pDerived->NameOf();        // Call virtual function.
   pDerived->InvokingClass(); // Call nonvirtual function.
}

0y01k918.collapse_all(it-it,VS.110).gifOutput

Derived::NameOf
Invoked by Base
Derived::NameOf
Invoked by Derived

Si noti che indipendentemente dal fatto che NameOf la funzione viene richiamata tramite un puntatore a Base o un puntatore a Derived, chiama la funzione per Derived.chiama la funzione per Derived poiché NameOf è una funzione virtuale ed entrambe pBase e pDerived punti a un oggetto di tipo Derived.

Poiché le funzioni virtuali vengono chiamate per gli oggetti di tipo classe, non è possibile dichiarare le funzioni globali statiche o come virtuale.

virtuale la parola chiave può essere utilizzata quando dichiara eseguire l'override di esecuzione in una classe derivata, ma non è necessaria, l'override delle funzioni virtuali sono sempre virtuali.

Le funzioni virtuali in una classe base devono essere definite a meno che non vengano dichiarate utilizzando il identificatore pure.(Per ulteriori informazioni sulle funzioni virtuali pure, vedere classi astratte).

Il meccanismo virtuale di chiamata di funzione può essere eliminato in modo esplicito sufficiente qualificare il nome della funzione utilizzando l'operatore di risoluzione dell'ambito (::).Considerare relative alla precedente di esempio Account classe.Per chiamare PrintBalance nella classe base, utilizzare codice analogo al seguente:

CheckingAccount *pChecking = new CheckingAccount( 100.00 );

pChecking->Account::PrintBalance();  //  Explicit qualification.

Account *pAccount = pChecking;  // Call Account::PrintBalance

pAccount->Account::PrintBalance();   //  Explicit qualification.

entrambe le chiamate a PrintBalance nell'esempio precedente eliminare il meccanismo virtuale di chiamata di funzione.

Vedere anche

Riferimenti

Accesso alle funzioni virtuali