Polymorphism - run-time vs. compile-time

S

Samee Zahur

Hello,
The other day I was rather shocked to find that I couldn't find
a good use for runtime polymorphism! Let me explain this a bit further
before you get shocked. Any function that I could previously write like
this:
void func1(Base& obj)
{
//...
obj.virmeth(); //Call virtual method
//...
}

Is now better written as this for most cases:
template <class T> void func1(T& obj)
{
//...
obj.virmeth(); //Call any method
//...
}

That way, I'll never incurr run-time overheads. Obviously, this
wouldn't
work if I'm trying to separate implementation from use, but this
question hit me so suddenly, that I really couldn't find a good answer
then. Now I figured out two situations where this isn't possible: when
return type must be polymorphic (or is that also used in automatic
template specialization?) ... or when catching exceptions. But I'd
still like to shake myself off this uneasy feeling by hearing a bit
more over which is more suitable when - and even in the cases I
mentioned, I'd like a little discussionW (exceptional cases etc.)

Samee
 
R

Rolf Magnus

Samee said:
Hello,
The other day I was rather shocked to find that I couldn't find
a good use for runtime polymorphism!

That would shock me too ;-)
Let me explain this a bit further before you get shocked. Any function
that I could previously write like this:
void func1(Base& obj)
{
//...
obj.virmeth(); //Call virtual method
//...
}

Is now better written as this for most cases:
template <class T> void func1(T& obj)
{
//...
obj.virmeth(); //Call any method
//...
}

That way, I'll never incurr run-time overheads. Obviously, this
wouldn't work if I'm trying to separate implementation from use, but this
question hit me so suddenly, that I really couldn't find a good answer
then. Now I figured out two situations where this isn't possible: when
return type must be polymorphic (or is that also used in automatic
template specialization?) ... or when catching exceptions. But I'd
still like to shake myself off this uneasy feeling by hearing a bit
more over which is more suitable when - and even in the cases I
mentioned, I'd like a little discussionW (exceptional cases etc.)

What if the actual type of the object is not determined at compile time, but
at runtime? Think of one classic example - a drawing program. The user can
draw circles, rectangles, text, whatever. When painting the objects on the
screen, the program goes through the list of objects and renders them all.
How does the program know at compile time, which paint function to call for
each of the objects?
 
K

Karl Heinz Buchegger

Samee said:
Hello,
The other day I was rather shocked to find that I couldn't find
a good use for runtime polymorphism! Let me explain this a bit further
before you get shocked. Any function that I could previously write like
this:
void func1(Base& obj)
{
//...
obj.virmeth(); //Call virtual method
//...
}

Is now better written as this for most cases:
template <class T> void func1(T& obj)
{
//...
obj.virmeth(); //Call any method
//...
}

That's not better.
The important part in polymorphism is exactly that: You don't
know the runtime type T during compile time. Well, if you
don't know it, how should the compiler know when it instantiates
the template?
 
S

Samee Zahur

To everyone, thanks ...
Even these textbook examples did unclog my mind quite a bit.

Samee
 
?

=?ISO-8859-1?Q?Tr0n=B2?=

Karl said:
That's not better.
The important part in polymorphism is exactly that: You don't
know the runtime type T during compile time. Well, if you
don't know it, how should the compiler know when it instantiates
the template?

You don't know it?
You mean - when you do:

int main () {
std::vector<std::string> test = "woop";
std::string * p2test = test;
func1(test);
return 0;
}

You DON'T know test?
Now, I personally think polymorphism is to generalize the function so
you don't have to write out several different versions of the same
function for different data types.

Please, explain..
And that code, I make no claims it is compilable - nor 100% correct....
I don't like pointers much.
 
K

Karl Heinz Buchegger

Tr0n² said:
You don't know it?
You mean - when you do:

int main () {
std::vector<std::string> test = "woop";
std::string * p2test = test;
func1(test);
return 0;
}

You DON'T know test?

The OP was talking about polymorphism.
The above has nothing to do with polymorphism, the above is
simply a pointer to an object.
Now, I personally think polymorphism is to generalize the function so
you don't have to write out several different versions of the same
function for different data types.

You obviously haven't understood what polymorphism is for and
what problem it solves.

Eg.

class Animal
{
public:
virtual void MakeNoise() {}
};

class Cat : public Animal
{
public:
virtual void MakeNoise() { std::cout << "Miau\n"; }
};

class Dog : public Animal
{
public:
virtual void MakeNoise() { std::cout << "Wuff\n"; }
};

void foo( Animal* pAnimal )
{
pAnimal->MakeNoise(); // here is the polymorphic call
// does pAnimal point to a Cat
// or a Dog? Nobody knows at this
// place. But it doesn't matter.
// Thanks to polymorphism the correct
// MakeNoise() function for Cats and/or Dogs
// is called.
}

int main()
{
Animal* Pets[2];

Pets[0] = new Cat;
Pets[1] = new Dog;

foo( Pets[0] );
foo( Pets[1] );

delete Pets[0];
delete Pets[1];
}

I invite you now to find a way to rewrite MakeNoise and foo
using templates without altering main() such that the program
behaves the very same.

Good luck!
 
R

Rolf Magnus

Tr0n² said:
You don't know it?
You mean - when you do:

int main () {
std::vector<std::string> test = "woop";
std::string * p2test = test;
func1(test);
return 0;
}

You DON'T know test?

You do know it. But this is not an example for polymorphism.
Just let's try another example, where polymorphism is actually used:

#include <vector>
#include <string>
#include <iostream>

class Base
{
public:
virtual void do_something() = 0;
virtual ~Base() {}
};

class Derived1 : public Base
{
public:
virtual void do_something()
{
std::cout << "We're Derived1\n";
}

virtual ~Derived1()
{
std::cout << "Destroyed a Derived1\n";
}
};

class Derived2 : public Base
{
public:
virtual void do_something()
{
std::cout << "Now this is a Derived2\n";
}

virtual ~Derived2()
{
std::cout << "Oh no, I'm such a young Derived2, don't kill me\n";
}
};

int main()
{
std::vector<Base*> vec;
std::cout << "Instance of which type to add?";
std::string name;

for(;;)
{
std::cin >> name;

if (name == "end")
break;

if (name == "Derived1")
vec.push_back(new Derived1);
else
vec.push_back(new Derived2);
}

for (int i = 0; i < vec.size(); ++i)
vec->do_something();

for (int i = 0; i < vec.size(); ++i)
delete vec;
}

Now, please rewrite that to use templates instead of virtual functions.
Now, I personally think polymorphism is to generalize the function so
you don't have to write out several different versions of the same
function for different data types.

No, it's not. That's what templates are for.
 
?

=?ISO-8859-1?Q?Tr0n=B2?=

Rolf said:
Tr0n² wrote:
Now, please rewrite that to use templates instead of virtual functions.




No, it's not. That's what templates are for.

Ahhh - thank you very much, Karl and Rolf.
I also say thank you for not taking it the wrong way, and simply
pointing at me and laughing instead of throwing the proverbial stick!

I half understand now... It's to do with objects with virtual functions
- the actions of which can change depending on the object.

And yes, I'm at the start of my journey down the yellow brick road - but
I'm sure not going to stop at the first crack.

Thanks for your assistance.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top