Compartilhar via


Funções virtuais

Uma função virtual é uma função de membro que você esperava ser redefinido em classes derivadas.Quando você faz referência a um objeto de classe derivada, usando um ponteiro ou uma referência para a classe base, você pode chamar uma função virtual para o objeto e executar a versão da classe derivada da função.

Funções virtuais Certifique-se de que a função correta é chamada de um objeto, independentemente da expressão usada para fazer com que a função chamada.

Suponha que uma classe base contém uma função declarada como virtual e uma classe derivada define a mesma função.A função da classe derivada é invocada para objetos derivados da classe, mesmo que ele é chamado usando um ponteiro ou uma referência para a classe base.O exemplo a seguir mostra uma classe base que fornece uma implementação da PrintBalance função e duas classes derivadas

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

No código anterior, as chamadas para PrintBalance são idênticos, exceto para o objeto pAccount aponta para.Porque PrintBalance é virtual, a versão da função definida para cada objeto é chamado.O PrintBalance função nas classes derivadas CheckingAccount e SavingsAccount a função na classe base "substituir" Account.

Se uma classe é declarada que não fornece uma implementação de substituição da PrintBalance função, a implementação padrão da classe base Account é usado.

Funções em classes derivadas substituem as funções virtuais em classes base somente se o seu tipo é o mesmo.Uma função em uma classe derivada não pode diferir de uma função virtual em uma classe base no seu tipo de retorno apenas; a lista de argumentos deve diferentes também.

Ao chamar uma função usando referências ou ponteiros, as seguintes regras se aplicam:

  • Uma chamada para uma função virtual é resolvida de acordo com para o tipo de objeto para o qual ele é chamado.

  • Uma chamada para uma função nonvirtual é obtida de acordo com o tipo de referência ou o ponteiro.

O exemplo a seguir mostra as funções como virtuais e nonvirtual se comportam quando chamado através de ponteiros:

// 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(pt-br,VS.110).gifSaída

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

Observe que, independentemente se a NameOf função é invocada por meio de um ponteiro para Base ou um ponteiro para Derived, ele chama a função de Derived.Ele chama a função de Derived porque NameOf é uma função virtual e ambos pBase e pDerived aponte para um objeto do tipo Derived.

Porque funções virtuais são chamadas somente para objetos de tipos de classe, você não pode declarar globais ou estáticas funções como virtual.

O virtual palavra-chave pode ser usada quando a declaração de funções de substituição em uma classe derivada, mas não é necessário; substituições de funções virtuais são sempre virtuais.

Funções virtuais na classe base devem ser definidas, a menos que eles são declarados usando o puro especificador.(Para obter mais informações sobre funções virtuais puras, consulte Classes abstratas.)

O mecanismo de chamada de função virtual pode ser suprimido pelo explicitamente o nome da função usando o operador de escopo de resolução de qualificação (::).Considere o exemplo anterior que envolvam a Account classe.Para chamar PrintBalance na classe base, use o código, como a seguir:

CheckingAccount *pChecking = new CheckingAccount( 100.00 );

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

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

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

As duas chamadas para PrintBalance no exemplo anterior, suprimir o mecanismo de chamada de função virtual.

Consulte também

Referência

Acesso a funções virtuais