Why use virtual functions? [duplicate]
Asked Answered
M

4

45

Possible Duplicate:
Can someone explain C++ Virtual Methods?

I have a question regarding to the C++ virtual functions.

Why and when do we use virtual functions? Can anyone give me a real time implementation or use of virtual functions?

Miniver answered 11/1, 2012 at 18:6 Comment(1)
I created a blog post just for this sake, because I found it difficult to explain it when a kid asked me "why virtual functions"? nrecursions.blogspot.in/2015/06/…Lieutenancy
S
60

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.

Stroboscope answered 11/1, 2012 at 18:9 Comment(3)
What if we don't use virtual and just redefine them in subclasses such as Line and Triangle. What would be difference there?Tautomer
If the function was not virtual in the base class, you could not access the derived classes version via the base class pointer.Clammy
Sorry, still a little confused here. Would it be correct to say that virtual functions are for when you don't know which version of a function you'll need until runtime, but you'll also need an instantiation of the base class some time before then? Because it seems like I could still get by without virtual functions and not knowing what I need until runtime by just creating subclasses and instantiating the proper class once I know. So it seems the you'll also need an instantiation of the base class some time before is critical, right? Aka: calling the derived function through base pointerZootomy
A
27

You use virtual functions when you need handle different objects in the same way. It`s called polymorphism. Let's imagine you have some base class - something like classical Shape:

    class Shape
    {
        public:
           virtual void draw() = 0;
           virtual ~Shape() {}
    };

    class Rectange: public Shape
    {
        public:
            void draw() { // draw rectangle here } 
    };


    class Circle: public Shape
    {
        public:
           void draw() { // draw circle here }
    };

Now you can have vector of different shapes:

    vector<Shape*> shapes;
    shapes.push_back(new Rectangle());
    shapes.push_back(new Circle());

And you can draw all shapes like this:

    for(vector<Shape*>::iterator i = shapes.begin(); i != shapes.end(); i++)
    {
          (*i)->draw();
    }

In this way you are drawing different shapes with one virtual method - draw(). Proper version of method is selected based on run time information about type of object behind pointer.

Notice When you use virtual functions you can declare them as pure virtual(like in class Shape, just place " = 0" after method proto). In this case you won't be able to create instance of object with pure virtual function and it will be called Abstract class.

Also notice "virtual" before destructor. In case when you are planning work with objects through pointers to their base classes you should declare destructor virtual, so when you call "delete" for base class pointer, all chain of destructors will be called and there won't be memory leaks.

Alys answered 11/1, 2012 at 18:19 Comment(0)
S
23

Think of animals class, and derived from it are cat, dog and cow. Animal class has a

virtual void SaySomething()
{
    cout << "Something";
}

function.

Animal *a;
a = new Dog();
a->SaySomething();

Instead of printing "Something", dog should say "Bark", cat should say "Meow". In this example you see that a is a Dog, but there are some times that you have an animal pointer and don't know which animal it is. You don't want to know which animal it is, you just want the animal to say something. So you just call virtual function and cats will say "meow" and dogs will say "bark".

Of course, SaySomething function should have been pure virtual to avoid possible errors.

Scutellation answered 11/1, 2012 at 18:14 Comment(4)
Thank your answer was satisfactory....Miniver
I am not quite follow about your last sentence "SaySomething function should have been pure virtual to avoid possible errors." could you please make an example of this.Scabbard
Sorry for the late reply. Consider this, a developer creates a new class inheriting our animal class (say, Fox ) and forgets to override SaySomething method. If you use the virtual method I provided, Fox instances will say "Something", which is not right. If we declared SaySomething as pure virtual, we wouldn't be able to instantiate Fox, a code containing new Fox(...) will raise an error. This way, the developer that created Fox class will be notified about his/her mistake in compile time. Compile time errors are good since they don't waste time :)Scutellation
But in languages that don't support pure virtual methods, a 'must implement' method should throw an exception. Java developers usually do that. Yet the main question here is, what does the fox say :PScutellation
R
1

You would use a virtual function to implement "polymorphism", in particular where you have an object, don't know what the actual underlying type is, but know what operation you want to perform on it, and the implementation of this (how it does it) differs dependent on what type you actually have.

Essentially what is commonly called the "Liskov Substitution Principle" named after Barbara Liskov who spoke about this around 1983.

Where you need to use dynamic runtime decisions where, at the point the code invoking the function is called, you do not know what types may pass through it, either now or in the future, this is a good model to use.

It isn't the only way though. There are all sorts of "callbacks" that can take a "blob" of data and you might have tables of callbacks dependent on a header block in the data that comes in, e.g. a message processor. For this there is no need to use a virtual function, in fact what you would probably use is sort-of how a v-table is implemented only with one entry (e.g. a class with just one virtual function).

Ragsdale answered 11/1, 2012 at 18:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.