Thursday, June 26, 2008

c++: v-methods overloaded by semantics

Let's assume you have such classes:

class A
{
 public:
  A() {cout << "A" << endl;}
  virtual void func() {cout << "A::func" << endl;}
};

class B : public A
{
 public:
  B() {cout << "B" << endl;}
  virtual void func() {cout << "B::func" << endl;}
};

class C
{
 public:
  virtual void func(A &a) {cout << "C::func" << endl; a.func();}
};

class D : public C
{
 public:
  virtual void func(B &b) {cout << "D::func" << endl; b.func();}
};
And when you have
A *a;
C *c;

a = new B;
c = new D;

c->func(*a);
This produces:
A
B
C::func
B::func
Costructors from A and B invoked, and ... method C::func invoked even c is an instance of D. Compiler doesn't know anything about method func from D and it's not overwritten in virtual table because it has different semantics, so C::func was executed. To let compiler correctly execute D::func the prototype of D::func should take a reference to A as an argument. Class D can be defined like this:
class D : public C
{
 public:
  virtual void func(A &a) {cout << "D::func" << endl; a.func();}
};
In this case the output will be
A
B
D::func
B::func

No comments: