#include <iostream>

class Derived;

class Base {
public:
    virtual void covariant_dom(const Base* x) const {
        std::cout << "Base::covariant_dom is called" << std::endl;
    }

    virtual void contravariant_dom(const Derived* x) const {
        std::cout << "Base::contravariant_dom is called" << std::endl;
    }
};

class Derived : public Base {
public:
    virtual void covariant_dom(const Derived* x) const {
        std::cout << "Derived::covariant_dom is called" << std::endl;
    }

    virtual void contravariant_dom(const Base* x) const {
        std::cout << "Derived::contravariant_dom is called" << std::endl;
    }
};

int main()
{
    Derived* derived = new Derived();
    Base* base = derived;

    base->covariant_dom(base); // "Base::covariant_dom is called"
    //derived->covariant_dom(base); // compile error

    base->contravariant_dom(derived); // "Base::contravariant_dom is called"

    return 0;
}
