Why Use Virtual Functions

Why use virtual functions?

You use virtual functions when you want to override a certain behavior (read method) for your derived class rather than the one implemented for the base class and you want to do so at run-time through a pointer to the base class.

The classic example is when you have a base class called Shape and concrete shapes (classes) that derive from it. Each concrete class overrides (implements a virtual method) called Draw().

The class hierarchy is as follows:

Class hierarchy

The following snippet shows the usage of the example; it creates an array of Shape class pointers wherein each points to a distinct derived class object. At run-time, invoking the Draw() method results in the calling of the method overridden by that derived class and the particular Shape is drawn (or rendered).

Shape *basep[] = { &line_obj, &tri_obj,
&rect_obj, &cir_obj};
for (i = 0; i < NO_PICTURES; i++)
basep[i] -> Draw ();

The above program just uses the pointer to the base class to store addresses of the derived class objects. This provides a loose coupling because the program does not have to change drastically if a new concrete derived class of shape is added anytime. The reason is that there are minimal code segments that actually use (depend) on the concrete Shape type.

The above is a good example of the Open Closed Principle of the famous SOLID design principles.

Why do we need virtual functions in C++?

Without "virtual" you get "early binding". Which implementation of the method is used gets decided at compile time based on the type of the pointer that you call through.

With "virtual" you get "late binding". Which implementation of the method is used gets decided at run time based on the type of the pointed-to object - what it was originally constructed as. This is not necessarily what you'd think based on the type of the pointer that points to that object.

class Base
{
public:
void Method1 () { std::cout << "Base::Method1" << std::endl; }
virtual void Method2 () { std::cout << "Base::Method2" << std::endl; }
};

class Derived : public Base
{
public:
void Method1 () { std::cout << "Derived::Method1" << std::endl; }
void Method2 () { std::cout << "Derived::Method2" << std::endl; }
};

Base* basePtr = new Derived ();
// Note - constructed as Derived, but pointer stored as Base*

basePtr->Method1 (); // Prints "Base::Method1"
basePtr->Method2 (); // Prints "Derived::Method2"

EDIT - see this question.

Also - this tutorial covers early and late binding in C++.

Why are virtual functions preferable over derived class objects?

The huge benefit that you get for using the base class pointer type and virtual functions is that you can have one single list that contains several different types of Shape and you can process them all in a single function where they will all have different behaviors due to their derived types.

As an example, I modified your code by adding the function DrawAllShapes that takes in a vector<Shapes*>&. (Be careful of using raw pointers. You really should use vector<std::unique_ptr<Shape>>&here or something like that.

You have incredible flexibility with this pattern that lets you call the same function on a collection of base class pointer objects but results in different behavior for every object in the collection depending on its derived type.

#include <iostream>
#include <vector>
using namespace std;

//////////////////////////////////////////////////////
//base class
class Shape {

public:
virtual void draw() = 0; //pure virtual function
};

//derived classes
class Square : public Shape {

public:
void draw() {
cout << "Draw square" << endl;
}

};

class Circle : public Shape {

public:
void draw() {
cout << "Draw circle " << endl;
}

};

void DrawAllShapes(std::vector<Shape*>& shapes) {
for (int i = 0; i < shapes.size(); ++i) {
shapes[i]->draw();
}
}

//////////////////////////////////////////////////////
int main()
{
std::vector<Shape*> shapeVec{ new Square, new Circle, new Square, new Square, new Circle };
DrawAllShapes(shapeVec);

system("pause");
}

Also, imagine if you were using a prebuilt graphical library that already had a Shape class and several shapes defined. What if you wanted to add your own new type of Shape and have it work perfectly with all of the library's functions? All you would have to do is create your own derived class and implement all of the necessary virtual functions exposed by the library's Shape class and then you've literally extended the library beyond its original capabilities.

Why use virtual function instead of regular?

You can redefine it but it won't work in a polymorphic way.

so if I have a

class base
{
int foo(){ return 3; }
};

class Der : public base
{
int foo() {return 5;}
};

and then have a function that takes a base

void dostuff(base &b)
{
b.foo(); // This will call base.foo and return 3 no matter what
}

and I call it like this

Der D; 
dostuff(D);

Now if I change the base to

class base
{
virtual int foo(){ return 3; }
};

void dostuff(base &b)
{
b.foo(); // This will call the most derived version of foo
//which in this case will return 5
}

so the real answer is if you want to write common code that will call the correct function from the base it needs to be virtual.

Why are virtual functions in C++ called 'virtual'?

Virtuality, the quality of having the attributes of something without sharing its (real or imagined) physical form

^ http://en.wikipedia.org/wiki/Virtual

A C++ virtual function appears to be an ordinary function ("having the attributes of"), but the implementation that will be called is not shared out via the declaration, or for that matter via an inline implementation.

When is it appropriate to use virtual methods?

When you design a class you should have a pretty good idea as to whether it represents an interface (in which case you mark the appropriate overrideable methods and destructor virtual) OR it's intended to be used as-is, possibly composing or composed with other objects.

In other words your intent for the class should be your guide. Making everything virtual is often overkill and sometimes misleading regarding which methods are intended to support runtime polymorphism.

Why use virtual functions when base class pointer casting gives same result?

Your example appears to work, because there is no data, and no virtual methods, and no multiple inheritance. Try adding int value; to derivedclass1, const char *cstr; to derivedclass2, initialize these in corresponding constructors, and add printing these to corresponding show() methods.

You will see how show() will print garbage value (if you cast pointer to derivedclass1 when it is not) or crash (if you cast the pointer to derivedclass2 when class in fact is not of that type), or behave otherwise oddly.


C++ class member functions AKA methods are nothing more than functions, which take one hidden extra argument, this pointer, and they assume that it points to an object of right type. So when you have an object of type derivedclass1, but you cast a pointer to it to type derivedclass2, then what happens without virtual methods is this:

  • method of derivedclass2 gets called, because well, you explicitly said "this is a pointer to derivedclass2".
  • the method gets pointer to actual object, this. It thinks it points to actual instance of derivedclass2, which would have certain data members at certain offsets.
  • if the object actually is a derivedclass1, that memory contains something quite different. So if method thinks there is a char pointer, but in fact there isn't, then accessing the data it points to will probably access illegal address and crash.

If you instead use virtual methods, and have pointer to common base class, then when you call a method, compiler generates code to call the right method. It actually inserts code and data (using a table filled with virtual method pointers, usually called vtable, one per class, and pointer to it, one per object/instance) with which it knows to call the right method. So when ever you call a virtual method, it's not a direct call, but instead the object has extra pointer to the vtable of the real class, which tells what method should really be called for that object.


In summary, type casts are in no way an alternative to virtual methods. And, as a side note, every type cast is a place to ask "Why is this cast here? Is there some fundamental problem with this software, if it needs a cast here?". Legitimate use cases for type casts are quite rare indeed, especially with OOP objects. Also, never use C-style type casts with object pointers, use static_cast and dynamic_cast if you really need to cast.

why do we actually have virtual functions?

ABSTRACT

In this paper, we discuss virtual functions in C++. Part zero explains how virtual functions are declared and overridden. Part one attempts (and perhaps fails) to explain how virtual functions are implemented. Part two is a sample program that uses the example classes defined in parts zero and one. Part three is the classic animal example given in every virtual function - polymorphism tutorial.

PART ZERO

A method of a class is said to be virtual if and only if its declared to be so.

class my_base
{
public:
void non_virtual_test() { cout << 4 << endl; } // non-virtual
virtual void virtual_test() { cout << 5 << endl; } // virtual
};

(Of course, I am assuming the programmer did not previously do anything like #define virtual.)

A class that redeclares and re-implements a non-virtual method of one of its bases is said to overload that method. A class that redeclares and re-implements a virtual method of one of its bases is said to override that method.

class my_derived : public my_base
{
public:
void non_virtual_test() { cout << 6 << endl; } // overloaded
void virtual_test() { cout << 7 << endl; } // overriden
};

PART ONE

When the compiler detects a class has virtual methods, it automatically adds a virtual method table (also known as vtable) to the class' memory layout. The result is similar to what would have been generated from compiling this code:

class my_base
{
//<vtable>
// The vtable is actually a bunch of member function pointers
protected:
void (my_base::*virtual_test_ptr)();
//</vtable>

// The actual implementation of the virtual function
// is hidden from the rest of the program.
private:
void virtual_test_impl() { cout << 5 << endl; }

// Initializing the real_virtual_test pointer in the vtable.
public:
my_base() : virtual_test_ptr(&my_base::virtual_test_impl) {}

public:
void non_virtual_test() { cout << 4 << endl; }
// The interface of the virtual function is a wrapper
// around the member function pointer.
inline void virtual_test() { *virtual_test_ptr(); }
};

When the compiler detects a class has overridden a virtual method, it replaces its associated entry in the vtable. The result is similar to what would have been generated from compiling this code:

class my_derived : public my_base
{
// The actual implementation of the virtual function
// is hidden from the rest of the program.
private:
void virtual_test_impl() { cout << 7 << endl; }

// Initializing the real_virtual_test pointer in the vtable.
public:
my_derived() : virtual_test_ptr(&my_derived::virtual_test_impl) {}

public:
void non_virtual_test() { cout << 6 << endl; }
};

PART TWO

Now that it's clear that virtual functions are implemented using vtables, which are nothing but a bunch of function pointers, it should be clear what this code does:

#include <iostream>

using namespace std;

class my_base
{
public:
void non_virtual_test() { cout << 4 << endl; }
virtual void virtual_test() { cout << 5 << endl; }
};

class my_derived : public my_base
{
public:
void non_virtual_test() { cout << 6 << endl; }
void virtual_test() { cout << 7 << endl; }
}

int main()
{
my_base* base_obj = new my_derived();

// This outputs 4, since my_base::non_virtual_test() gets called,
// not my_derived::non_virtual_test().
base_obj->non_virtual_test();

// This outputs 7, since the vtable pointer points to
// my_derived::virtual_test(), not to my_base::virtual_test().
base_obj->virtual_test();

// We shall not forget
// there was an object that was pointed by base_obj
// who happily lived in the heap
// until we killed it.
delete base_obj;

return 0;
}

PART THREE

Since no virtual function example is complete without an example with animals...

#include <iostream>

using namespace std;

class animal
{
public:
virtual void say_something()
{ cout << "I don't know what to say." << endl
<< "Let's assume I can growl." << endl; }

/* A more sophisticated version would use pure virtual functions:
*
* virtual void say_something() = 0;
*/
};

class dog : public animal
{
public:
void say_something() { cout << "Barf, barf..." << endl; }
};

class cat : public animal
{
public:
void say_something() { cout << "Meow, meow..." << endl; }
};

int main()
{
animal *a1 = new dog();
animal *a2 = new cat();
a1->say_something();
a2->say_something();
}

What's the point of a final virtual function?

Typically final will not be used on the base class' definition of a virtual function. final will be used by a derived class that overrides the function in order to prevent further derived types from further overriding the function. Since the overriding function must be virtual normally it would mean that anyone could override that function in a further derived type. final allows one to specify a function which overrides another but which cannot be overridden itself.

For example if you're designing a class hierarchy and need to override a function, but you do not want to allow users of the class hierarchy to do the same, then you might mark the functions as final in your derived classes.


Since it's been brought up twice in the comments I want to add:

One reason some give for a base class to declare a non-overriding method to be final is simply so that anyone trying to define that method in a derived class gets an error instead of silently creating a method that 'hides' the base class's method.

struct Base {
void test() { std::cout << "Base::test()\n"; }
};

void run(Base *o) {
o->test();
}

// Some other developer derives a class
struct Derived : Base {
void test() { std::cout << "Derived::test()\n"; }
};

int main() {
Derived o;
o.test();
run(&o);
}

Base's developer doesn't want Derived's developer to do this, and would like it to produce an error. So they write:

struct Base {
virtual void test() final { ... }
};

Using this declaration of Base::foo() causes the definition of Derived to produce an error like:

<source>:14:13: error: declaration of 'test' overrides a 'final' function
void test() { std::cout << "Derived::test()\n"; }
^
<source>:4:22: note: overridden virtual function is here
virtual void test() final { std::cout << "Base::test()\n"; }
^

You can decide if this purpose is worthwhile for yourself, but I want to point out that declaring the function virtual final is not a full solution for preventing this kind of hiding. A derived class can still hide Base::test() without provoking the desired compiler error:

struct Derived : Base {
void test(int = 0) { std::cout << "Derived::test()\n"; }
};

Whether Base::test() is virtual final or not, this definition of Derived is valid and the code Derived o; o.test(); run(&o); behaves exactly the same.

As for clear statements to users, personally I think just not marking a method virtual makes a clearer statement to users that the method is not intended to be overridden than marking it virtual final. But I suppose which way is clearer depends on the developer reading the code and what conventions they are familiar with.

Why use virtual functions when deriving hides base function?

To make polymorphism work you need to work on pointers or references. When you use dot operator on object that is neither pointer or reference then virtual table is not used to call proper virtual function.

To see how it works, create derived object dynamically, assign it to base class pointer and call your function on it. This will call implementation from your derived class.



Related Topics



Leave a reply



Submit