Udostępnij za pośrednictwem


Funkcje wirtualnych

Funkcję wirtualną jest funkcji składowej, przewidywaną przedefiniować klas pochodnych.Gdy odwołujesz się do obiektu klasy pochodnej przy użyciu wskaźnika lub odwołanie do klasy podstawowej, można wywołać funkcję wirtualną dla tego obiektu i wykonywanie klasy pochodnej wersję funkcji.

Funkcje wirtualnych upewnij się, że poprawne funkcja jest wywoływana dla obiektu, niezależnie od wyrażenie używane do tworzenie funkcji wywołania.

Załóżmy, że klasa podstawowa zawiera funkcja zadeklarowana jako wirtualnego i pochodne klasy definiuje tę samą funkcję.Funkcja z klasy pochodne jest wywoływana dla obiektów klasy pochodnej, nawet wtedy, gdy jest ona wywoływana przy użyciu wskaźnika lub odwołanie do klasy podstawowej.W poniższym przykładzie pokazano klasy podstawowej, który zapewnia implementację PrintBalance funkcji i dwóch klas pochodnych

// 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();   
}

W poprzednim kodzie wywołania PrintBalance , są identyczne, z wyjątkiem dla obiektu pAccount wskazuje.Ponieważ PrintBalance jest wirtualnych, wersja funkcję zdefiniowaną dla każdego obiektu jest wywoływana.PrintBalance Funkcji klas pochodnych CheckingAccount i SavingsAccount funkcji w klasie podstawowej "override" Account.

Jeżeli zadeklarowano klasę nie zapewnia nadrzędnych wykonania PrintBalance funkcji, domyślna implementacja z klasy bazowej Account jest używana.

Funkcje w klas pochodnych zastępują funkcje wirtualnych w klasach bazowych tylko wtedy, gdy ich typ jest taki sam.Funkcja w klasie pochodnej nie różnią się od funkcję wirtualną w klasie bazowej w jego typ zwracany tylko; Lista argumentów muszą być także różne.

Podczas wywoływania funkcji za pomocą wskaźników lub odwołania, stosuje się następujące zasady:

  • Wywołanie funkcji wirtualnych jest rozwiązane zgodnie z podstawowy typ obiektu, dla którego jest ona wywoływana.

  • Wywołanie funkcji niewirtualna został rozwiązany zgodnie z typem wskaźnik lub odwołania.

W poniższym przykładzie pokazano sposób wirtualnych i niewirtualna funkcji zachowują się po wywołaniu przez wskaźniki:

// 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(pl-pl,VS.110).gifDane wyjściowe

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

Należy zauważyć, że niezależnie od czy NameOf funkcja jest wywoływana za pomocą wskaźnika do Base lub wskaźnik do Derived, wywołuje funkcję dla Derived.Wywołuje funkcję dla Derived ponieważ NameOf jest funkcję wirtualną i zarówno pBase i pDerived wskaż obiektu typu Derived.

Ponieważ wirtualne funkcje są wywoływane tylko dla obiektów typu klasy, nie można zadeklarować funkcji globalnych lub statycznych, jak wirtualnego.

Wirtualnego w przypadku deklarowania funkcji nadrzędnych w klasie pochodnej można użyć słowa kluczowego, ale nie jest konieczne; zastępuje funkcje wirtualnych są zawsze wirtualnych.

Wirtualnego funkcji w klasie bazowej musi być zdefiniowana, chyba że są one zadeklarowane za pomocą czystego specyfikatora.(Aby uzyskać więcej informacji na temat czystego funkcji wirtualnych, zobacz Klasy abstrakcyjne.)

Mechanizm wywołania funkcji wirtualnych można pominąć przez jawnie kwalifikujących się nazwa funkcji za pomocą operatora zakres rozdzielczości (::).Należy wziąć pod uwagę wcześniejszego przykładu obejmujące Account klasy.Wywołanie PrintBalance w klasie bazowej, użyj kodu, takie jak następujące:

CheckingAccount *pChecking = new CheckingAccount( 100.00 );

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

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

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

Zarówno wywołania PrintBalance w poprzednim przykładzie wyłączyć mechanizm wirtualne wywołanie funkcji.

Zobacz też

Informacje

Dostęp do funkcji wirtualnych