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.
If you run this code, you'll end up with this.Code:#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); }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:Code: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
NOW when you run the same program, not changing any other code, you'll end up with this...Code: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; } };
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.Code: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
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:
When you run the program now, your output will look like this:Code:void func(simpleClass& obj) { cout << "'Func' Shows: "; obj.show(); cout << " "; obj.simpleClass::show(); }
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.Code: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
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:
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.)Code:class simpleClass { protected: int numby; public: simpleClass(int x) : numby(x) {} // Now this class method is abstract! virtual void show() = 0; };
Hope you learned something about the virtual function, and maybe a little more about how polymorphism works!
Last edited by ZekeDragon; 06-29-2011 at 11:43 AM.
Wow I changed my sig!
Very nice! +rep
Nice +rep![]()
Hey! Check out my new Toyota keyboaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Nice little demo+rep
Simple and neat !
rep+
I cannot +rep you right now, nicely done though!
Interested in participating in community events?
Want to harness your programming skill and turn it into absolute prowess?
Come join our programming events!
There are currently 1 users browsing this thread. (0 members and 1 guests)
Bookmarks