[ From the blog ]
Polymorphism allows for different function implementations to be called, depending on values only known at run time. For instance:
class BaseA {
public:
virtual void foo(){cout<<"Base";};
};
class A: public BaseA {
public:
void foo() {cout<<"Child";};
};
A a;
BaseA & base = a;
base.foo();
Will print "Child".
"Pair polymorphism" is when you want a specific function implementation to be called based on the run time value of two different instances of a class. For instance in the case of:
class BaseA {};
class BaseB {
public:
virtual void foo (BaseA & a) = 0;
};
class A: public BaseA {};
class B: public BaseB {
public: void foo (A & a);
};
You would want that somehow "void B::foo (A & a)" will be called. The code I posted does not do this.
There is a way to do this, but it requires for a class to know about the implementation classes. It is not a problem in some cases. However, sometimes you want to have an abstraction layer.
An abstraction layer is a set of classes or interfaces, that have no methods or "don't know" anything about the classes that implement them. For instance you can have a graphics abstraction layer.
You could implement this layer with DirectX. However, this layer will make it easier to afterwards add an implementation with OpenGL without having to make a lot of changes, even if the game is already completed.
How are we going to have a "pair polymorphism" in this case? One solution is using dynamic casting. You can cast a pointer of a parent class to it's child class(in case the run time value really points to an instance of that class).
Some code:
class BaseA {};
class BaseB {
public:
virtual void foo (BaseA & a) = 0;
};
class A: public BaseA {};
class B: public BaseB {
public:
void foo (BaseA & a) {
foo2 (dynamic_cast(a));
}
void foo2 (A & a);
};
I was asked by someone how this can be done without dynamic casting, because he doesn't like dynamic casting. I found a way, but it ain't pretty, and I honestly can't find any advantage of using this code instead of just using dynamic casting. But here it is:
class BaseA {
public:
virtual void DynamicCast() = 0;
};
class BaseB {
public:
virtual void foo (BaseA & base) = 0;
};
class A;
class Caster {
public:
A * a;
};
class A: public BaseA {
public:
Caster * c;
void DynamicCast() { c->a = this; }
};
class B: public BaseB {
public:
Caster * c;
void foo (BaseA & base) {
base.DynamicCast();
foo2 (c->a);
}
void foo2 (A & a);
};