Omitting the virtual
keyword declares a method as non-virtual. Simply speaking, declaring
a method as virtual enables overriding, declaring a method as non-virtual disables overriding.
theAccount->display();
The display()
method that is called depends on whether
theAccount
pointer references a generic Account
, Deposit
account or Current
account (the dynamic type - sometimes called late binding).
So why are non-virtual methods required? If in the rare circumstance of declaring a class that you know will have no derived classes, you can use non-virtual methods. When virtual methods are used the compiler does not know for certain the type of an object until run-time, so the compiler inserts additional code to evaluate the dynamic type at run-time and call the correct method. Removing this feature allows slightly faster program execution. Non-virtual can also be used if for some reason you wish that a method cannot be over-ridden (e.g. the constructor of an object).
Most Object Oriented Programming languages only support virtual methods, but strangely enough in C++ non-virtual is the default setting!
So in the Virtual case:
...
class Account{
public:
virtual string getType() { return "Generic Account"; };
};
class Current: public Account{
public:
virtual string getType() { return "Current Account"; };
};
class Deposit: public Account{
public:
virtual string getType() { return "Deposit Account"; };
};
int main()
{
// Note that all pointers have the static type 
Account
Account *a = new Account();
Account *b = new Current();
Account *c = new Deposit();
cout << "Pointer a Displayed: " << a->getType() << endl;
cout << "Pointer b Displayed: " << b->getType() << endl;
cout << "Pointer c Displayed: " << c->getType() << endl;
}
(The full source code for this "virtual" example is here -
NonVirtualTest.cpp
)
This program will result in the output:
Pointer a Displayed: Generic Account Pointer b Displayed: Current Account Pointer c Displayed: Deposit Account
Since the getType()
method is virtual the getType()
method
most closely associated with the object will be called, not the getType()
method associated
with the pointer. Note that you only need to declare the method as virtual
in the base class
declaration and it will be virtual in all child classes, regardless if the virtual
keyword is
used or not. Redefining a virtual method is called overriding.
In the non-virtual case:
.. class Account{ public: string getType() { return "Generic Account"; }; }; class Current: public Account{ public: string getType() { return "Current Account"; }; }; class Deposit: public Account{ public: string getType() { return "Deposit Account"; }; }; int main() { Account *a = new Account(); Account *b = new Current(); Account *c = new Deposit(); cout << "Pointer a Displayed: " << a->getType() << endl; cout << "Pointer b Displayed: " << b->getType() << endl; cout << "Pointer c Displayed: " << c->getType() << endl; }
(The full source code for this "non-virtual" example is here -
NonVirtualTest2.cpp
)
This program will result in the output:
Pointer a Displayed: Generic Account Pointer b Displayed: Generic Account Pointer c Displayed: Generic Account
Since the methods are now non-virtual the getType()
associated with the pointer
will always be called. So, the Account::getType()
will always be called.
The destructor is always virtual as we require different actions in destructing an object, for example in:
Current
account - on destruction, send
a statement.
Deposit
account - on destruction, calculate
interest and then send a statement.
So, for example:
class Deposit :: public Account { //states public: virtual ~Deposit(); //destructor - always virtual }; Deposit::~Deposit() { //calculate interest //send statement. }
© 2006
Dr. Derek Molloy
(DCU).