virtual functions.. why??

I've just been reading about virtual functions, and whilst i understand how they work , i'm struggling to see a use??.I've read they are more useful on larger projects??.

If i have a member function called area() lets say. If i then have derived classes each with a member function area() as well, each will perform this function in a unique way according to it's class. This is correct,right ??

I know i'm looking at this from a beginners point of view. Please excuse my ignorance yet again.

I've also checked this web site for a better explanation and examples , and although it explains brilliantly(as always) , i'm still struggling slightly with the 'point' of them.
Virtual functions allows you to do type-specific behavior without knowing the actual type. It's a concept that's referred to as "polymorphism".

Polymorphism allows you to write generic code that will work with any kind of object, even if those objects will work differently under the hood.

Let's say you have a parent class 'Shape' and child classes 'Square' and 'Circle'. Shape has a virtual function Draw() which draws the shape to the screen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Shape
{
public:
  virtual void Draw() = 0;
};

class Square
{
public:
  virtual void Draw() { /*...*/ }
};

class Circle
{
public:
  virtual void Draw() { /*...*/ }
};


From the sound of it you understand how the above works.

The reason this is useful is it lets you deal with "Shapes" without caring whether or not they're circles or squares.

Let's say we have a list of shapes that we want to draw:

1
2
3
4
5
6
7
8
9
10
11
12
13
std::vector<Shape*> shapes;

// make a list of various kinds of shapes:
shapes.push_back( new Circle );
shapes.push_back( new Square );
shapes.push_back( new Circle );
shapes.push_back( new Circle );
shapes.push_back( new Square );
shapes.push_back( new Square );

// now if you want to draw all these shapes to the screen:
for(int i = 0; i < shapes.size(); ++i)
  shapes[i]->Draw();  // this will appropriately draw a Circle or a Square 


By using Shape* pointers and virtual functions, we can write code that will work with any Shape. Not just with Circles or Squares.
okay.. i understand that. So are you saying they're really only meant for very rudimentary functions like speak(),walk(),draw(),etc.. with no parameters?, i'm guessing you have to leave the base class virtual function as generic as possible.

By the way- in your example you've made inherited classes like circle and square virtual?. i've read somewhere you only make the base class or first declaration of the function 'virtual'.

Again apologies for what must seem like daft questions , you obviously know a lot more about this than me.

Just to trying to understand. Thanks
So are you saying they're really only meant for very rudimentary functions like speak(),walk(),draw(),etc.. with no parameters


They're meant for functions that can apply to any/all derived types. The number of parameters has nothing to do with it. It's just that all of the examples you're seeing are simple =P

It's a conceptual thing. The base class 'Shape' represents a shape. It would have functions that do things which can apply to any kind of shape. In the above example, I would want to be able to Draw any kind of shape.

However, for some tasks, you would need to know the specific kind of shape in order to perform it. That's where virtual functions come in handy. They let you call derived class functions without knowing exactly what the derived class is.

i'm guessing you have to leave the base class virtual function as generic as possible.


That's true in a sense. You only want the base class to do things that apply to ALL derived types. If your base class does something that only works with a specific derived type, it turns the code into a big mess.

For example, the code in Shape shouldn't assume that the shape is a Square, because it might not be. So no functions or anything should take any parameters or anything that is specific to a Square.

By the way- in your example you've made inherited classes like circle and square virtual?. i've read somewhere you only make the base class or first declaration of the function 'virtual'.


It doesn't matter. If it's virtual in the base class, it will be virtual in the derived class even if you omit the virtual keyword.

I choose to have the virtual keyword in my derived classes for additional clarity.

But either way works fine and has the same effect.
Hello again. i understand what has been said in thread above . However i'm still struggling a little bit....

I have a class called circle. I also have a class derived from circle called cylinder.Both have a member function called draw(), each obviously perform different functions and draw circles and cylinders.

If i create an object called cylinder1 from the cylinder class and execute the function cylinder1.draw() , the software knows to use the draw() function from the cylinder class??. It does this automatically i believe without any 'virtual' command line in it's declaration? Is this true??.

I thought this was part ofthe benefits of c++ and encapsulation ??.

i understand abstract classes and pure virtual functions and know why i would use them,but i think that is not what i'm talking about here...

or...

are we saying that the beauty of virtual functions is to be found when using pointers to refers to objects. (sorry... 'beauty' probably isn't the right word!)

i know i'm missing a point here somewhere and appologise again for my ignorance.

If i create an object called cylinder1 from the cylinder class and execute the function cylinder1.draw() , the software knows to use the draw() function from the cylinder class??.


If you have a cylinder object, yes. It will call cylinder::draw() even if it's not virtual.

are we saying that the beauty of virtual functions is to be found when using pointers to refers to objects.


Yes.

Consider the following:

1
2
3
4
5
6
7
Cylinder foo;
Circle* p = &foo;  // since Cylinder is derived from Circle

// assuming 'draw' is not virtual:
p->draw();  // draws a circle!  not a cylinder!

// if draw is virtual, then p->draw() will draw a cylinder instead 


The reason why you'd want to use a base pointer like the above is because you can treat many different types the same way. For example:

1
2
3
4
5
6
7
8
vector<Shape*> myshapes;
myshapes.push_back( new Cylinder );  // put a bunch of different shapes in our vector
myshapes.push_back( new Circle );
myshapes.push_back( new Square );

// now draw all the shapes
for(int i = 0; i < myshapes.size(); ++i)
  myshapes[i]->Draw();  // this will draw the appropriate shape 
If i create an object called cylinder1 from the cylinder class and execute the function cylinder1.draw() , the software knows to use the draw() function from the cylinder class??. It does this automatically i believe without any 'virtual' command line in it's declaration?
Yes.

are we saying that the beauty of virtual functions is to be found when using pointers to refers to objects
Correct. Without pointers, none of this vtable/virtual function stuff kicks in. There is always an explicit level of indirection (use of a pointer or reference) when doing object oriented programming in C++, and an implicit use in pure OO languages.

C++ is a dual paradigm language.

It can be used as a better procedural language. That's where inline functions, constructors/destructors/copy control, non-virtual members, operator overloading and templates come in. In this mode there is no compromise in efficiency.

It can be used as an object oriented language with static type checking. That's where inheritance, virtual functions and exceptions come in. Most object oriented languages allow any class to send any message to any other class. These errors are detected at run-time. C++ attempts to remove this class of error by restricting what messages can be sent to a class by only allowing you to only call methods on classes that appear in the class declaration.

Terms (like class) are reused in different contexts and can have different meanings in these contexts. (In procedural contexts, a class is an abstract data type, in object oriented contexts, a class is an object.)

One problem is the two paradigms often aren't introduced seperately. We're just taught the language without regard to this seperation.
Since terms like polymorphism, inheritance etc are classic OO teachings, ever wonder why the Standard C++ STL is based on templates instead ? In my early years, I was thinking maybe the C++ standard committee members favor performance over OO theories ?

A person who is in touch with Java FIRST before touching C++ STL specifically will have a hard time catching up cuz C++ can be both procedural and OO. Although Java has Generics their underlying implementation is nothing like how C++ STL is implemented.

I believe templates programming is something C++ STL has shown to the world that it can be applied to large scale software engineering project. This will at least answer to those Java die-hard that there are other viable programming paradigm beyond OO realm who coincidentally are also OO die-hard cuz Java is created to be OO all the way :)
Since terms like polymorphism, inheritance etc are classic OO teachings, ever wonder why the Standard C++ STL is based on templates instead ?


"instead"? It uses both.

Container classes like vector/list/map/etc make sense to be templated so that they can manage any type.

Other classes like iostream/fstream/sstream make use of abstraction and polymorphism as you'd expect.
Thanks Disch for providing me new info. So C++ STL uses BOTH templates and OOP I see. In this aspect I feel C++ is much more flexible than Java but this also indicate there are more grounds to cover in C++ which implies doing C++ maintenance will be much tougher compared to Java.

In my country, C++ developers are generally paid better than Java developers for a reason. But yet the available pool of Java developers greatly surpass those C++ fellows. Universities should re-introduce C++ back to their curriculum to cure this phenomenon :)
Topic archived. No new replies allowed.