Sdílet prostřednictvím


Virtuální funkce

Virtuální funkce je členské funkce, která očekáváte předefinovat v odvozené třídy.Při odkazu na objekt odvozené třídy pomocí ukazatele nebo odkaz na základní třídy můžete virtuální funkce pro daný objekt a spouštět funkce verze odvozené třídy.

Virtuální funkce zajistit, že správné funkce je volána pro objekt bez ohledu na výraz, který slouží k volání funkce.

Předpokládejme, že základní třída obsahuje funkce deklarované jako virtuální a odvozené třídy definuje stejnou funkci.Funkce v odvozené třídě je vyvolán pro objekty odvozené třídy i v případě, že je volána, pomocí ukazatele nebo odkaz na základní třídy.Následující příklad zobrazuje základní třídy, který poskytuje implementaci PrintBalance funkci a dvou odvozené třídy

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

V předcházejícím kódu volání na PrintBalance jsou identické s výjimkou pro objekt pAccount odkazuje.Protože PrintBalance je virtuální, verze funkce definovaná pro každý objekt se nazývá.PrintBalance Funkce v odvozené třídy CheckingAccount a SavingsAccount "přepsat" funkce v základní třídě Account.

Pokud je třída deklarována neposkytuje převažující provádění PrintBalance funkce, výchozí implementace ze základní třídy Account se používá.

Funkce v odvozené třídy přepsat virtuální funkce v základní třídy pouze v případě, že jejich typ je stejný.Funkce v odvozené třídě nemůže lišit od virtuálních funkcí v základní třídě v pouze; návratový typ seznam argumentů musí také lišit.

Při volání funkce pomocí ukazatele nebo odkazy, platí následující pravidla:

  • Volání virtuální funkce základního typu objektu, pro který se nazývá vyřešen.

  • Volání funkce nonvirtual je vyřešen typu ukazatele nebo odkazu.

Následující příklad ukazuje, jak virtuální a nonvirtual funkce chování při volání prostřednictvím ukazatelů:

// 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(cs-cz,VS.110).gifVýsledek

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

Všimněte si, že bez ohledu zda NameOf prostřednictvím ukazatele na zavolání funkce Base nebo ukazatele na Derived, volá funkci pro Derived.Volá funkci pro Derived protože NameOf je virtuální funkce a oba pBase a pDerived přejděte na příkaz objekt typu Derived.

Pouze pro objekty typu třídy se nazývají virtuální funkce, proto nelze deklarovat globální nebo statické funkce jako virtuální.

Virtuální klíčových slov lze použít při deklarování funkce převažující v odvozené třídě, ale je zbytečné; virtuální jsou vždy přepíše virtuální funkce.

Virtuální funkce v základní třídě musí být definována, pokud jsou deklarovány pomocí čistého specifikátor.(Další informace o čistého virtuální funkce, viz Abstraktní třídy.)

Mechanismus virtuální volání funkce lze potlačit explicitně kvalifikováním názvu funkce pomocí operátoru rozsah rozlišení (::).Zvažte například starší zahrnující Account třídy.Volání PrintBalance v základní třídě použít například následující kód:

CheckingAccount *pChecking = new CheckingAccount( 100.00 );

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

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

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

Obě volání na PrintBalance v předchozím příkladu potlačit mechanismus virtuální volání funkce.

Viz také

Referenční dokumentace

Přístup k virtuální funkce