virtual function

Hi,
I am learning Virtual function in c++. I read Virtual function is member function that is used to achieve run time polymorphism. It is known that polymorphism means one name but multiple forms.But how run time polymorphism(i.e;one name multiple forms) is achieved through virtual function?

Please help me in understanding the concept.

Also,RUNTIME TIME POLYMORPHISM and METHOD OVERRIDING are synonyms?
Human language is often murky, so I will stick to C++-specific terms here.

A polymorphic object class is one that can change to be what you think it is.
That is kind of broad, so let us look at a real-world example that we use all the time in C++:

iostreams.

1
2
3
4
5
6
#include <iostream>

int main()
{
  std::cout << "Hello world!\n";
}

In this example we expect the words Hello world! to appear on the terminal. That is because std::cout is a specialization of a std::ostream that knows how to talk to the terminal.

But what if I wanted to write to a file?

1
2
3
4
5
6
7
#include <fstream>

int main()
{
  std::ofstream fout( "hello.txt" );
  fout << "Hello world!\n";
}

The fact that the code on line 6 looks nearly identical to the code on line 5 above is no coincidence. That is because both std::cout and fout are polymorphic instances of (or specializations of) a std::ostream.

We can use that to our advantage. Here we have a function that takes any kind of ostream:

1
2
3
4
5
6
7
#include <fstream>
#include <iostream>

void say_hello( std::ostream& outs )
{
  outs << "Hello world!\n";
}

Because both cout and fout are a kind of ostream, we can use the function for either:

9
10
11
12
13
14
15
int main()
{
  say_hello( std::cout );

  std::ofstream fout( "hello.txt" );
  say_hello( fout );
}

The reality is that cout and fout are very different underneath. One speaks to the terminal. The other speaks to a file. But BOTH are a kind of output stream and are, from our perspective when using them, the same. We can call them both “ostream”, but they know what they really are, and do the Right Thing™ then asked to write text to their output.

This is the power of polymorphism.


Runtime Polymorphism and Method Overriding are not synonyms, but they are related.

Method Overriding is the term for specializing the behavior of an object based its type:
  • ofstream has a function named operator<< that sends output to a file
  • std::cout has a different function named operator<< that sends output to the terminal
And so on.

Runtime Polymorphism is the term for actively choosing the correct function to use, based on the object’s true type.

We have seen this in the example above. The say_hello() function has, as argument, an ostream. That is all it knows about it.

When say_hello() says outs << "Hello world!";, it doesn’t know where the text actually goes.

But fout knows what it really is, and chooses the correct operator<<() function to write text.
  • if fout is an ofstream, use ofstream::operator<<().
  • if fout is cout, use cout.operator<<()
And so on.

The choice based on the actual type (“polymorphism”) happens when the function is called (at “runtime”).


This is a very brief overview. You should start googling around object orientation and abstraction, encapsulation, inheritance, and polymorphism. And, despite what morons say, Wikipedia is an excellent place to start reading.


Hope this helps.
how run time polymorphism(i.e;one name multiple forms) is achieved through virtual function?

Lets continue with:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <fstream>
#include <iostream>

void say_hello( std::ostream& outs )
{
  outs << "Hello world!\n";
}

int main()
{
  say_hello( std::cout );

  std::ofstream fout( "hello.txt" );
  say_hello( fout );
}

Compiler produces object code for functions say_hello() and main().
The main() contains two calls to say_hello(). On each the execution must jump from code of main() into the code of say_hello() (and return back to main afterwards).

The code in main() contains the address where the code of say_hello() starts.

Member functions are no different. Their code has an address too.

However, when a class has a virtual function, then the class object has an additional hidden data member: a lookup table. When you call a virtual function, you, the caller have address of that table and you read the address of the actual function code from that table.

All ostream objects have such table.
When std::cout is created, it writes the address of the code of cout.operator<<() into the table.
When ofstream object is created, it writes the address of the code of ofstream::operator<<() into the table.
You look at ostream object. Your call to operator<< is redirected to whatever address is in the table of that object.
Topic archived. No new replies allowed.