Search code examples
c++covariance

Covariance and Hiding in C++


Can someone please explain the reason behind input in each line ?

Class A {
bool f(A* a) { return true; }
}
class B : public A {
bool f(B* b) { return false; }
}
void f() {
A* a = new A();
A* ab = new B();
B* b = new B();
a->f(a); a->f(ab); a->f(b); // true, true, true
ab->f(a); ab->f(ab); ab->f(b); // true, true, true
b->f(a); b->f(ab); b->f(b); // error, error, false
}

Solution

  • B has two non-virtual methods with the same name: bool f(A*) and bool f(B*).

    Normally, these would be overloads; but since one was inherited from a base class, it's hidden by the latter. It's still accessible, it just needs some special syntax to call it, for example:

    B b;
    B* param;
    b.f(param);    // calls B::f(B*)
    b.B::f(param); // same
    b.A::f(param); // calls the hidden A::f(A*)
    

    So:

    a->f(a); a->f(ab); a->f(b);
    

    This one is easy: a is of type A*, so A::f(A*) will be called and argument of type B* will be converted to A*.

    ab->f(a); ab->f(ab); ab->f(b);
    

    Same thing happens, since ab is also of type A*.

    b->f(a); b->f(ab);
    

    These can't work since b is of type B* and b->f can only refer to B::f(B*) (A::f is hidden). You can't implicitly convert from A* to B*.

    You can mention the hidden method explicitly, though:

    b->A::f(a); b->A::f(ab);

    And the last works, simply calls B::f(B*):

    b->f(b);
    

    Sample at ideone


    Remarks:

    It doesn't matter here whether the functions are virtual or not. They have different argument types, so one can't override another. One can only hide the other.

    C++ allows covariant return types (you might want to have virtual A* foo() in A and virtual B* foo() in B if the args match). C++ doesn't allow covariant or contravariant argument types, though.