Was this page helpful?
Your feedback about this content is important. Let us know what you think.
Additional feedback?
1500 characters remaining
Export (0) Print
Expand All

Virtual Functions

A virtual function is a member function that you expect to be redefined in derived classes. When you refer to a derived class object using a pointer or a reference to the base class, you can call a virtual function for that object and execute the derived class's version of the function.

Virtual functions ensure that the correct function is called for an object, regardless of the expression used to make the function call.

Suppose a base class contains a function declared as virtual and a derived class defines the same function. The function from the derived class is invoked for objects of the derived class, even if it is called using a pointer or reference to the base class. The following example shows a base class that provides an implementation of the PrintBalance function and two derived classes

// deriv_VirtualFunctions.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;

class __declspec(dllexport) Account
{
public:
   Account( double d );  // Constructor.
   virtual double GetBalance();         // Obtain balance.
   virtual void   PrintBalance();       // Default implementation.
private:
    double _balance;
};

// Implementation of constructor for Account.
Account::Account( double d )
{
   _balance = d;
}

// Implementation of GetBalance for Account.
double Account::GetBalance()
{
   return _balance;
}
// Default implementation of PrintBalance.
void Account::PrintBalance()
{
   cerr << "Error. Balance not available for base type."
        << endl;
}

class __declspec(dllexport) CheckingAccount : public Account
{
public:
   void PrintBalance();
};

// Implementation of PrintBalance for CheckingAccount.
void CheckingAccount::PrintBalance()
{
   cout << "Checking account balance: " << GetBalance();
}

class __declspec(dllexport) SavingsAccount : public Account
{
public:
   void PrintBalance();
};

// Implementation of PrintBalance for SavingsAccount.
void SavingsAccount::PrintBalance()
{
   cout << "Savings account balance: " << GetBalance();
}

int main()
{
}

The PrintBalance function in the derived classes is virtual because it is declared as virtual in the base class, Account. To call virtual functions such as PrintBalance, code such as the following can be used:

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

In the preceding code, the calls to PrintBalance are identical, except for the object pAccount points to. Because PrintBalance is virtual, the version of the function defined for each object is called. The PrintBalance function in the derived classes CheckingAccount and SavingsAccount "override" the function in the base class Account.

If a class is declared that does not provide an overriding implementation of the PrintBalance function, the default implementation from the base class Account is used.

Functions in derived classes override virtual functions in base classes only if their type is the same. A function in a derived class cannot differ from a virtual function in a base class in its return type only; the argument list must differ as well.

When calling a function using pointers or references, the following rules apply:

  • A call to a virtual function is resolved according to the underlying type of object for which it is called.
  • A call to a nonvirtual function is resolved according to the type of the pointer or reference.

The following example shows how virtual and nonvirtual functions behave when called through pointers:

// deriv_VirtualFunctions2.cpp
// compile with: /EHsc

class __declspec(dllimport) Account
{
public:
                   Account( double d );  // Constructor.
    virtual double GetBalance();         // Obtain balance.
    virtual void   PrintBalance();       // Default implementation.
private:
    double _balance;
};

class __declspec(dllimport) CheckingAccount : public Account
{
public:
    void PrintBalance();
};

class __declspec(dllimport) SavingsAccount : public Account
{
public:
    void PrintBalance();
};


#include <iostream>

using namespace std;
// Declare a base class.
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";
}

// Declare a derived class.
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.
}

Output

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

Note that regardless of whether the NameOf function is invoked through a pointer to Base or a pointer to Derived, it calls the function for Derived. It calls the function for Derived because NameOf is a virtual function, and both pBase and pDerived point to an object of type Derived.

Because virtual functions are called only for objects of class types, you cannot declare global or static functions as virtual.

The virtual keyword can be used when declaring overriding functions in a derived class, but it is unnecessary; overrides of virtual functions are always virtual.

Virtual functions in a base class must be defined unless they are declared using the pure-specifier. (For more information about pure virtual functions, see Abstract Classes.)

The virtual function-call mechanism can be suppressed by explicitly qualifying the function name using the scope-resolution operator (::). Consider the earlier example involving the Account class. To call PrintBalance in the base class, use code such as the following:

CheckingAccount *pChecking = new CheckingAccount( 100.00 );

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

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

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

Both calls to PrintBalance in the preceding example suppress the virtual function-call mechanism.

See Also

Access to Virtual Functions

Show:
© 2015 Microsoft