Compartir a través de


Funciones virtuales

Una función virtual es una función miembro que espera volver a definir en clases derivadas.Cuando se hace referencia a un objeto de la clase derivada mediante un puntero o una referencia a la clase base, puede llamar a una función virtual para ese objeto y ejecutar la versión de la clase derivada de la función.

Las funciones virtuales garantizan que la función correcta esté denominada para un objeto, independientemente de la expresión utilizada para realizar la llamada de función.

suponga que una clase base contiene una función declarada como virtual y una clase derivada define la misma función.La función de clase derivada se invoca para los objetos de la clase derivada, aunque se realiza mediante un puntero o una referencia a la clase base.El ejemplo siguiente se muestra una clase base que proporciona una implementación de la función de PrintBalance y dos clases 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();   
}

En el código anterior, las llamadas a PrintBalance son idénticas, excepto los puntos de pAccount de objetos en.Dado que PrintBalance es virtual, la versión de la función definido para cada objeto se denomina.La función de PrintBalance en clases derivadas CheckingAccount y SavingsAccount “reemplaza” la función en la clase base Account.

Si se declara una clase que no proporciona una implementación de reemplazo de la función de PrintBalance , la implementación predeterminada de la clase base Account se utiliza.

Las funciones en clases derivadas reemplazan funciones virtuales en clases base sólo si el tipo es el mismo.Una función en una clase derivada no puede diferir de una función virtual en una clase base en su tipo de valor devuelto sólo; la lista de argumentos debe diferir también.

Al llamar a una función mediante punteros o referencias, se aplican las siguientes reglas:

  • Una llamada a una función virtual se resuelve como el tipo de objeto para el que se llama.

  • Una llamada a una función no virtual se resuelve según el tipo de puntero o de referencia.

El ejemplo siguiente se muestra cómo las funciones virtuales y no virtual se comportan cuando se llama con punteros:

// 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(es-es,VS.110).gifOutput

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

Observe que independientemente de la función de NameOf se invoca a través de un puntero a Base o un puntero a Derived, llama a la función para Derived.Llama a la función para Derived porque NameOf es una función virtual, y pBase y punto de pDerived a un objeto de Derivedescrito.

Dado que se llama a las funciones virtuales sólo para los tipos de los objetos de clase, no puede declarar las funciones globales o de estático como virtual.

La palabra clave de virtual se puede usar para declarar reemplazar funciona en una clase derivada, pero no es necesario; reemplazos de funciones virtuales son siempre virtual.

Las funciones virtuales en una clase base deben definirse a menos que se declaran mediante el especificador puro.(Para obtener más información sobre las funciones virtuales puras, vea clases abstractas.)

El mecanismo virtual de la llamada de función no suprimido explícitamente calificando el nombre de función con el operador de resolución de ámbito (::).considere el ejemplo anterior que implica la clase de Account .Para llamar a PrintBalance en la clase base, utilice el código como el siguiente:

CheckingAccount *pChecking = new CheckingAccount( 100.00 );

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

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

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

Las dos llamadas a PrintBalance en el ejemplo anterior se suprime el mecanismo de llamada de función virtual.

Vea también

Referencia

Acceso a las funciones de Virtual