This post describes how function resolution is typically (but not always) implemented by compilers.
For non-virtual functions, the compiler matches a function call with the corresponding function definition at compile-time. This is known as
static binding.
Dynamic Polymorphism
When a member function is declared
virtual, it can be overridden in a class that directly, or indirectly, derives from the class where it was declared (the base class).
class Base
{
public:
virtual ~Base() {}
virtual void hello() = 0; // hello is pure virtual
};
class A : public Base
{
public:
void hello() { std::cout << "A says 'hello'\n"; }
};
class B : public Base
{
public:
void hello() { std::cout << "B says 'hello'\n"; }
};
void sayHello(Base& helloer)
{
helloer.hello();
}
int main()
{
Base *a = new A;
Base *b = new B;
sayHello(*a);
sayHello(*b);
delete a;
delete b;
}
This program generates the following output:
A says 'hello'
B says 'hello'
Even though
helloer is a reference to the base class, which function that will actually be called depends on the type of object we pass to
sayHello(). This means, of course, that the function call to
hello() must be resolved at run-time. This is referred to as
dynamic binding. Internally this is achieved using two constructs known as
v-tables (virtual tables, or dispatch tables) and
v-pointers.
- A v-table is created for every class that: declares one or more virtual functions, or overrides a virtual function. (A)
- Such class is called a polymorphic class.
- Functions that override virtual functions from a parent class are adjusted in the v-table of the derived class. (B)
- The function call is resolved at run-time, from the matching index in the v-table, pointed to by the actual object's v-pointer. (C)
- Each object of a polymorphic class has its own v-pointer, but there is only one v-table per class.
- The v-tables and v-pointers are added by the compiler, and not visible to the programmer.
class Fruit
{
public:
Fruit()
: m_color("fruit-colored"),
m_peeled(false)
{}
virtual ~Fruit() {}
virtual void eat();
virtual void peel();
void setColor(const std::string &color) { m_color = color; }
const std::string &color() const { return m_color; }
protected:
std::string m_color;
bool m_peeled;
};
void Fruit::eat()
{
std::cout << "Now eating this " << m_color << " fruit!\n";
}
void Fruit::peel()
{
if (!m_peeled)
m_peeled = true;
}
class Orange : public Fruit
{
public:
Orange()
: Fruit()
{
m_color = "orange";
}
void eat();
};
void Orange::eat()
{
if (m_peeled) {
Fruit::eat();
} else {
std::cout << "Can't eat orange before peeling it!\n";
}
}
int main()
{
Fruit *fruit1 = new Fruit;
Fruit *fruit2 = new Orange;
Fruit *fruit3 = new Orange;
fruit1->eat(); // Now eating this fruit-colored fruit!
fruit2->eat(); // Can't eat orange before peeling it!
fruit2->peel();
fruit2->eat(); // Now eating this orange fruit!
std::cout << fruit2->color(); // orange
delete fruit1;
delete fruit2;
delete fruit3;
return 0;
}
Run this example from codepad:
http://codepad.org/QUyLRq6l
1 comments:
Thanks for post.I do agree your blog for quiz programming concepts, which is very helpful to grow up your knowledge. keep sharing more
AWS training in chennai | AWS training in annanagar | AWS training in omr | AWS training in porur | AWS training in tambaram | AWS training in velachery
Post a Comment