Virtual functions? Inheritance? Why use them???

Started by
26 comments, last by Ghostface 22 years, 8 months ago
Compared to most of the people here, I am new to programming. The only language that I have any experience with is C++, which I have been learning for the past 9-10 months. But, something perplexes me: why would anyone want to use virtual functions? They seem kind of pointless to me. Why not just override the base class''s function? From all of the examples I''ve seen, it seems that in order to use a virtual function, you must have an instance of a base class that points to an instance of a derived class, but must decide which function to use at runtime. Or something like that. It''s all gibberish to me. So...someone help me out please.
------------------------------"I do not feel obliged to believe that the same God who has endowed us with sense, reason, and intellect has intended us to forgo their use. " - Galileo Galilei
Advertisement
Well, you''re sort of on the right track here. If a class''s function is virtual, it can be overridden in a child class. This is very, very useful. Here''s a stupid little example...suppose you have a generic CEnemy class, with a virtual function attack(). Then, suppose you have two child classes, CTroll and COgre. Each of these also has an attack(). Now, the magic of virtual functions:
  CEnemy* pEnemy = new CTroll(...);pEnemy->attack(); // CTroll''s attack() function gets calledpEnemy = new COgre(...);pEnemy->attack(); // COgre''s attack() function gets called  

I hope you can see just how useful this can be. Another example would be if you are iterating through a list of enemies, and each enemy is of a different type. All you have to do is call each enemy''s attack() function, and you know that the correct one will be called.

~~~~~~~~~~
Martee
ReactOS - an Open-source operating system compatible with Windows NT apps and drivers
A virtual function basically forces derived objects to also perform the function according to what the base class has for that virtual function prior to performing the derived class''s overriden function.

The most common example of this is a destructor. It is wise to make destructors virtual due to the fact that you might need to delete allocated memory in the base class. For instance:

class Base{public:  Base() { myItem = new ITEM; } // default constructor  virtual ~Base() { delete myItem; } // virtual destructor  ITEM *myItem;}class Derived : public Base{public:  Derived();  // default constructor  virtual ~Derived(); // virtual destructor} 


In the previous example, myItem was allocated as memory that will require specific deletion. If the destructor were not virtual, then any constructed instances of Derive would not "be aware" that the memory needed to be deleted. Due to the fact that the destructor is virtual, the destructor for Base will be called, and the memory properly released, before the destructor for Derive will be completed. This is why destructors are always declared as virtual.

Other examples of wanting to use this functionality would be anything you wish to repeat across all derived classes. For instance, if you always wanted to draw something on every derived view, you could make the OnDraw virtual to force the same thing to be drawn first for all views.

There are several gotchas regarding this involving calling member functions from within virtual functions and vice versa, but I think this is enough to digest for now *smile*

-fel
~ The opinions stated by this individual are the opinions of this individual and not the opinions of her company, any organization she might be part of, her parrot, or anyone else. ~
I forgot to note that base class constructors are implicitly virtual due to the fact that the base class must be constructed in conjunction with (and previous to, for that matter) any derived classes, though constructors are not labelled as such... in case there''s any confusion as to how the Base constructor got called in the first place.

-fel
~ The opinions stated by this individual are the opinions of this individual and not the opinions of her company, any organization she might be part of, her parrot, or anyone else. ~
Your game might have a lot of objects that need to be updated every tick. They might be of many different types but fundamentally they need to get updated every tick. So you want to store them all in a list or a vector and update them all by iterating through the list right? You can''t do that unless you use pointers to derived classes. So what you do is you make a base class Updatable and give it a virtual method Update(). Then derive all of the things you want to be able to update from this class and implement the method. Now you can loop through. Oh and you can''t override a non virtual function, the word virtual means overridable. It might seem like you can but you aren''t doing what you think you are.

Another common use is for implementing what is known as the "strategy pattern". Let''s say you have a monster type and you need to make AI for it. Every now and then it appraises the situation and decides what to do. You could have a case statement, and have code for each situation. That is probably the best solution if you only need simple AI. However if you want things to be more complex or flexible it is time to break out inheritance. Make a Reaction class with a HandleSituation() method. Have Reaction* variables for all the different situations and put subclasses in them. Now in the case statement instead of putting the code directly call the HandleSituation method of the appropriate Reacton variable. There are some nice benefits to doing this. For one you can change behavior at runtime. You might have a spell that makes monsters laugh in response to certain situations, now it is easy, just swap in a subclass that does just that. You can also use the same set of Reaction classes to do all the AI for all your monsters, it makes things easier.

There are more uses of inheritance too but they mostly revolve the basic concept of changing behavior while retaining the same interface.
The main contribution is interface reuse, which means that you build on a foundation of ABSTRACT base classes. Without virtual functions and the accompanying vtbls you couldn''t do this.

This is what COM is all about.
VK
I would like to thank everyone for their attempts to help me to understand the use of virtual functions, but I''m afraid that I still don''t understand. Could someone please give me a practical example of something that you would NOT want to do/cannot do without virtual functions?

They still seem pointless to me. But then again, I''m a novice programmer...
------------------------------"I do not feel obliged to believe that the same God who has endowed us with sense, reason, and intellect has intended us to forgo their use. " - Galileo Galilei
I think you should buy a good C++ book...

And don´t tell me you can´t afford it...Get a job of some sort !
-------------Ban KalvinB !
I happen to have two C++ books (Teach Yourself C++ in 21 Days and Practical C++). And neither one of them does a very good of explaining the practicality/uses of virtual functions.

And I''m only 15, which is not quite old enough to get a job at most places
------------------------------"I do not feel obliged to believe that the same God who has endowed us with sense, reason, and intellect has intended us to forgo their use. " - Galileo Galilei
I delivered local newspapers when I was 14 or 15 years old.

But laws differ I know....
-------------Ban KalvinB !

This topic is closed to new replies.

Advertisement