Jump to content


Check out our Community Blogs

Register and join over 40,000 other developers!


Recent Status Updates

View All Updates

Photo
- - - - -

Virtual Functions and Polymorphism

polymorphism

  • Please log in to reply
5 replies to this topic

#1 ZekeDragon

ZekeDragon

    CC Leader

  • Retired Mod
  • PipPipPipPipPipPipPip
  • 1263 posts

Posted 12 August 2009 - 02:10 PM

It occured to me that with the STL series I'm working on, it might be important to talk a little bit about Virtual functions. Declaring functions as virtual makes the use of classes easier to manage, and allows for polymorphism, a central tenet of Object-Oriented programming. I know that these kinds of topics are difficult for newer programmers to pick up, and as such, I'll attempt to explain it as simply and with as much detail as possible to help people understand. Polymorphism, to put it rather simply, means that a derived class (a class that inherits properties from a base class) is able to change what a function declared as virtual in the base class actually does. We'll take the code example below as a set of classes that do NOT exhibit polymorphism.
#include <iostream>
using namespace std;

class simpleClass
{
protected:
    int numby;
public:
    simpleClass(int x) : numby(x)
    {}
    // NO virtual function declared here.
    void show() { cout << "Class Num: " << numby << endl; }
};

class derivedClass : public simpleClass
{
public:
    derivedClass(int x) : simpleClass(x)
    {}

    void show() { cout << "Class Num Doubled: " << numby * 2 << endl; }
};

class anotherDerivedClass : public derivedClass
{
public:
    anotherDerivedClass(int x) : derivedClass(x)
    {}

    void show() { cout << "Class Num Tripled: " << numby * 3 << endl; }
};

void func(simpleClass& obj)
{
    cout << "'Func' Shows:      ";
    obj.show();
}

int main() {
    simpleClass cls(100);
    derivedClass cls2(100);
    anotherDerivedClass cls3(100);
    cout << "Class cls Shows:   ";
    cls.show();
    func(cls);
    cout << endl << "Class cls2 Shows:  ";
    cls2.show();
    func(cls2);
    cout << endl << "Class cls3 Shows:  ";
    cls3.show();
    func(cls3);
}
If you run this code, you'll end up with this.
Class cls Shows:   Class Num: 100
'Func' Shows:      Class Num: 100

Class cls2 Shows:  Class Num Doubled: 200
'Func' Shows:      Class Num: 100

Class cls3 Shows:  Class Num Tripled: 300
'Func' Shows:      Class Num: 100
The function func requests a simpleClass reference, which as you can see when virtual is not used, the function simply calls the simpleClass version of the show function each time it is called, regardless of whether or not the base class OR one of the derived classes is used in the call. Sometimes this is what you want, but usually, it's not. So how can we get func to call our derived classes versions of show? Easy, we declare in the base class that show is a virtual function! Just add this small amount to the code in the following code snippet, in context:
class simpleClass
{
protected:
    int numby;
public:
    simpleClass(int x) : numby(x)
    {}
    // Now this class method is virtual!
    virtual void show() { cout << "Class Num: " << numby << endl; }
};
NOW when you run the same program, not changing any other code, you'll end up with this...
Class cls Shows:   Class Num: 100
'Func' Shows:      Class Num: 100

Class cls2 Shows:  Class Num Doubled: 200
'Func' Shows:      Class Num Doubled: 200

Class cls3 Shows:  Class Num Tripled: 300
'Func' Shows:      Class Num Tripled: 300
When func is called, it figures out based on which class was passed as a parameter to func which version of show to use! You'll also notice that you don't need to give it's derived class methods a virtual keyword either, since it always acts as virtual from there on.

So, what if you want to use the base classes version of show in the func function? Is that impossible? Not at all! Let's add another line of code to exemplify this, changing the func function now:
void func(simpleClass& obj)
{
    cout << "'Func' Shows:      ";
    obj.show();
    cout << "                   ";
    obj.simpleClass::show();
}
When you run the program now, your output will look like this:
Class cls Shows:   Class Num: 100
'Func' Shows:      Class Num: 100
                   Class Num: 100

Class cls2 Shows:  Class Num Doubled: 200
'Func' Shows:      Class Num Doubled: 200
                   Class Num: 100

Class cls3 Shows:  Class Num Tripled: 300
'Func' Shows:      Class Num Tripled: 300
                   Class Num: 100
When you add the "obj.simpleClass::show();" line, the compiler realizes you're using specifically the simpleClass namespace for the show function, and so despite show being declared as virtual, it still uses the base class version instead of the derived classes versions.

Finally, in the case of abstract classes (IE classes that aren't supposed to be declared and implemented in themselves, and are only supposed to be inherited by other derived classes), you can define virtual functions as such, and allow each derived class to implement their own version of that function:
class simpleClass
{
protected:
    int numby;
public:
    simpleClass(int x) : numby(x)
    {}
    // Now this class method is abstract!
    virtual void show() = 0;
};
This changes the function into an abstract method and in turn, the class an abstract class. If you try to declare an object as simpleClass now, the compiler will complain that you cannot declare an abstract class, so DO NOT USE THIS CODE IN THE ABOVE EXAMPLE, IT WILL NOT WORK! (unless you change it around so that there are no references to the simpleClass version of show and no direct declarations of simpleClass.)

Hope you learned something about the virtual function, and maybe a little more about how polymorphism works!

Edited by ZekeDragon, 29 June 2011 - 10:43 AM.

  • 4
If you enjoy reading this discussion and are thinking about commenting, why not click here to register and start participating in under a minute?

#2 Guest_Jordan_*

Guest_Jordan_*
  • Guest

Posted 12 August 2009 - 02:47 PM

Very nice! +rep
  • 0

#3 marwex89

marwex89

    CC Mentor

  • VIP Member
  • PipPipPipPipPipPipPipPip
  • 2857 posts

Posted 12 August 2009 - 05:24 PM

Nice +rep ;)
  • 0
Hey! Check out my new Toyota keyboaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

#4 WingedPanther73

WingedPanther73

    A spammer's worst nightmare

  • Moderator
  • 17757 posts
  • Location:Upstate, South Carolina
  • Programming Language:C, C++, PL/SQL, Delphi/Object Pascal, Pascal, Transact-SQL, Others
  • Learning:Java, C#, PHP, JavaScript, Lisp, Fortran, Haskell, Others

Posted 12 August 2009 - 05:54 PM

Nice little demo :) +rep
  • 0

Programming is a branch of mathematics.
My CodeCall Blog | My Personal Blog

My MineCraft server site: http://banishedwings.enjin.com/


#5 Turk4n

Turk4n

    ???

  • Expert Member
  • PipPipPipPipPipPipPip
  • 1919 posts
  • Location:Sweden
  • Programming Language:C, Java, PHP, Python, Bash
  • Learning:C++, C#, JavaScript, Visual Basic .NET, Others

Posted 23 August 2009 - 08:50 PM

Simple and neat !
rep+
  • 0

#6 MathX

MathX

    CC Leader

  • Expert Member
  • PipPipPipPipPipPipPip
  • 1038 posts
  • Programming Language:Java

Posted 23 August 2009 - 10:51 PM

I cannot +rep you right now, nicely done though!
  • 0

Interested in participating in community events?
Want to harness your programming skill and turn it into absolute prowess?
Come join our programming events!






Also tagged with one or more of these keywords: polymorphism

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download