In modern C++ software, a virtual function is a function in a base class or struct that can be redefined in derived classes or structs. They are member functions whose behavior can be overridden in derived classes. The virtual function specifier is the ‘virtual’ specifier to declare a virtual function in a base class. In this post, we explain how we can use virtual function specifiers in modern C++.
Table of Contents
What is a virtual function specifier in modern C++?
A virtual function is a function in a base class or struct that can be redefined in derived classes or structs. They are member functions whose behavior can be overridden in derived classes.
The virtual function specifier is the ‘virtual‘ specifier to declare a virtual function in a base class. It is used by declaring the function prototype in the usual way and then prefixing the declaration with the virtual keyword.
Here is the syntax of a virtual function:
1 2 3 |
virtual function_declaration; |
To declare a pure function (which automatically declares an abstract class), prefix the prototype with the virtual keyword, and set the function equal to zero.
Here is an example to virtual function and pure virtual function in C++:
1 2 3 4 5 |
virtual int funct1(void); // A virtual function declaration. virtual int funct2(void) = 0; // A pure function declaration. |
How to use virtual function specifier in modern C++?
When you declare virtual functions, keep these guidelines in mind:
- They can be member functions only.
- They can be declared a friend of another class.
- They cannot be a static member.
A virtual function does not need to be redefined in a derived class. You can supply one definition in the base class so that all calls will access the base function.
To redefine a virtual function in any derived class, the number and type of arguments must be the same in the base class declaration and in the derived class declaration. The case for redefined virtual functions differing only in return type is discussed below. A redefined function is said to override the base class function.
You can also declare the functions int Base::Fun(int) and int Derived::Fun(int) even when they are not virtual. In such a case, int Derived::Fun(int) is said to hide any other versions of Fun(int) that exist in any base classes. In addition, if class Derived defines other versions of Fun(), (that is, versions of Fun() with different signatures) such versions are said to be overloaded versions of Fun().
Is there a simple example of a virtual function in modern C++?
Here is a simple example how you can use virtual function specifier in modern C++.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
class Tx { virtual void myf() { std::cout << "My Virtual Function" << std::endl; } }; class Ta : public Tx { void myf() { std::cout << "My Derived Function" << std::endl; } }; |
How to use a virtual function return type in modern C++?
Generally, when redefining a virtual function, you cannot change just the function return type. To redefine a virtual function, the new definition (in some derived class) must exactly match the return type and formal parameters of the initial declaration. If two functions with the same name have different formal parameters, C++ considers them different, and the virtual function mechanism is ignored.
However, for certain virtual functions in a base class, their overriding version in a derived class can have a return type that is different from the overridden function. This is possible only when both of the following conditions are met:
- The overridden virtual function returns a pointer or reference to the base class.
- The overriding function returns a pointer or reference to the derived class.
Is there a full example of a virtual function specifier in modern C++?
Here is an very educational full example about virtual function specifier that can be found in docwiki of C++ Builder.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
#include <iostream> struct X {};// Base class. struct Y : X {};// Derived class. struct B { virtual void vf1(); virtual void vf2(); virtual void vf3(); void f(); virtual X* pf();// Return type is a pointer to base. This can // be overridden. }; class D : public B { public: virtual void vf1();// Virtual specifier is legal but redundant. void vf2(int);// Not virtual, since it's using a different // arg list. This hides B::vf2(). // char vf3();// Illegal: return-type-only change! void f(); Y* pf();// Overriding function differs only // in return type. Returns a pointer to // the derived class. }; void extf() { D d;// Instantiate D B* bp = &d;// Standard conversion from D* to B* // Initialize bp with the table of functions // provided for object d. If there is no entry for a // function in the d-table, use the function // in the B-table. bp->vf1(); // Calls D::vf1 bp->vf2(); // Calls B::vf2 since D's vf2 has different args bp->f(); // Calls B::f (not virtual) X* xptr = bp->pf();// Calls D::pf() and converts the result // to a pointer to X. D* dptr = &d; Y* yptr = dptr->pf();// Calls D::pf() and initializes yptr. // No further conversion is done. } int main() { } |
In the full example above, if a base class B
and class D
(derived publicly from B
) each contain a virtual function vf
, then if vf
is called for an object d
of D
, the call made is D::vf()
, even when the access is via a pointer or reference to B
.
For more information on this feature, see Explicit virtual overrides Proposal document.
C++ Builder is the easiest and fastest C and C++ IDE for building simple or professional applications on the Windows, MacOS, iOS & Android operating systems. It is also easy for beginners to learn with its wide range of samples, tutorials, help files, and LSP support for code. RAD Studio’s C++ Builder version comes with the award-winning VCL framework for high-performance native Windows apps and the powerful FireMonkey (FMX) framework for cross-platform UIs.
There is a free C++ Builder Community Edition for students, beginners, and startups; it can be downloaded from here. For professional developers, there are Professional, Architect, or Enterprise version.