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.
}
Saí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.