virtual functions and dynamic binding

M

Mike Stevenson

Hi. I'm in the process of re-learning all the C++ I forgot from
college, and I'm starting to get into some virgin (or at least only a
couple times) territory. I have some questions about casting a pointer
from a base class to a derived class. For example:

class Base{
public:
Base() {}
virtual ~Base() {}
void func1(int);
virtual void func2(int);
protected:
int foo;
};
class Deriv : public Base{
public:
virtual void func2(int);
void func3(int);
protected:
int bar;
};

So let's say I make a pointer thus: Base *ptr = new Deriv;. As I
understand it (please correct me if I'm wrong), ptr will use Base::func1
and have access to foo. Since it's defined as virtual, it knows to use
Deriv::func2. What I'm confused about is that ptr will not be able to
use func3 or access bar, saying that class Base does not contain those
things. I guess what I don't understand is, why bother casting the
pointer do the derived type when it can't access all its members?
What's the advantage over using Deriv *ptr = new Deriv?

Cheers,
Mike
 
N

Noah Roberts

Mike said:
Hi. I'm in the process of re-learning all the C++ I forgot from
college, and I'm starting to get into some virgin (or at least only a
couple times) territory. I have some questions about casting a pointer
from a base class to a derived class. For example:

class Base{
public:
Base() {}
virtual ~Base() {}
void func1(int);
virtual void func2(int);
protected:
int foo;
};
class Deriv : public Base{
public:
virtual void func2(int);
void func3(int);
protected:
int bar;
};

So let's say I make a pointer thus: Base *ptr = new Deriv;. As I
understand it (please correct me if I'm wrong), ptr will use Base::func1
and have access to foo. Since it's defined as virtual, it knows to use
Deriv::func2. What I'm confused about is that ptr will not be able to
use func3 or access bar, saying that class Base does not contain those
things. I guess what I don't understand is, why bother casting the
pointer do the derived type when it can't access all its members?
What's the advantage over using Deriv *ptr = new Deriv?

You are not casting to the derived type in you example code. You are
assigning a derived type to a pointer of the base type - essentially
casting to the base type.

The advantage is genericness and polymorphism.

You are correct that the ptr to a base does not resolve any names
contained in the devired type even if the ptr is actually to a derived
type. The compiler doesn't really know what the pointer is actually
pointing at, it only knows the static naming of the ptr type. The
names are resolved at compile time and the linkage to the function is
created then. Virtual functions link to a virtual function translator
of some sort (usually a ptr table) and so are called in an indirect
fassion...but the name has to exist in the scope of the call or the
linkage cannot happen.

Calling func2 would work because the base class has a name called func2
and the linkage will be virtual. That function could then call any of
the functions it has access to because as far is it is conserned the
pointer is to a derived type (this is a pointer to your type no matter
what type of pointer was used to call you). So a call to ptr->func2()
could result in calls to functions not existing in the base even though
you couldn't call them directly without a downcast.

The issues surrounding this are well described in "Exceptional C++".
You may consider buying that book.
 
J

Jim Langston

Mike Stevenson said:
Hi. I'm in the process of re-learning all the C++ I forgot from
college, and I'm starting to get into some virgin (or at least only a
couple times) territory. I have some questions about casting a pointer
from a base class to a derived class. For example:

class Base{
public:
Base() {}
virtual ~Base() {}
void func1(int);
virtual void func2(int);
protected:
int foo;
};
class Deriv : public Base{
public:
virtual void func2(int);
void func3(int);
protected:
int bar;
};

So let's say I make a pointer thus: Base *ptr = new Deriv;. As I
understand it (please correct me if I'm wrong), ptr will use Base::func1
and have access to foo. Since it's defined as virtual, it knows to use
Deriv::func2. What I'm confused about is that ptr will not be able to
use func3 or access bar, saying that class Base does not contain those
things. I guess what I don't understand is, why bother casting the
pointer do the derived type when it can't access all its members?
What's the advantage over using Deriv *ptr = new Deriv?

You could call func3 using this pointer if you cast it to a Deriv. Which is
where you would usually use RTTI to make sure it was actually pointing to a
Deriv first.

The reason to do this is so you could have a container of different types of
classes.

Make sure you enable RTTI in your compiler to get the following code to
work. Output is:
walking
woof woof
walking
meow!

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

class animal
{
public:
virtual ~animal() {}
void walk() { std::cout << "walking" << std::endl; }
};

class dog: public animal
{
public:
~dog() {}
void bark() { std::cout << "woof woof" << std::endl; }
};

class cat: public animal
{
public:
~cat() {}
void meow() { std::cout << "meow!" << std::endl; }
};

int main()
{
std::vector<animal*> Animals;

Animals.push_back( new dog );
Animals.push_back( new cat );

for ( std::vector<animal*>::iterator it = Animals.begin(); it !=
Animals.end(); ++it )
{
(*it)->walk();

dog* ThisDog = dynamic_cast< dog* >( (*it) );
if ( ThisDog != NULL )
{
ThisDog->bark();
}

cat* ThisCat = dynamic_cast< cat* >( (*it) );
if ( ThisCat != NULL )
{
ThisCat->meow();
}
}

std::string wait;
std::cin >> wait;

}
 

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

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top