all. I can't undestand why the bellow code need a cast to work. Someone can explain it?
class Base {
};
class Derived : public Base {
};
class Class {
public:
Derived member;
};
...
Derived obj;
Base *ptrObj = &obj; // ok, no cast needed
Derived Class::* ptr = &Class::member; // ok
Base Class::* ptr = &Class::member; // wrong, need cast, why?
Because if Base
were allowed (covariant), you could then do this, which is a no-no:
Base Class::* ptr = &Class::member;
Class obj;
obj.*ptr = Base(); // <-- assigned a Base into a Derived field?!
At the same time, pointers-to-members cannot be contravariant either, because otherwise you could do this, which is also a no-no:
struct Class2 {
Base member;
};
Derived Class2::* ptr2 = &Class2::member;
Class2 obj2;
obj2.member = Base();
Derived& d = obj2.*ptr2; // <-- assigned a Base into a Derived
So, pointers-to-members are neither covariant nor contravariant, but are invariant: the type must match exactly.
Ok, I got your point Chris, but your first example works for ordinary pointers. Why should it not work for member pointers too? See the code bellow.
Derived obj;
Base *ptr = &obj;
*ptr = Base(); // it's weird, but ok
The second example will not work even for ordinary pointers, since downcasting is not allowed without cast. So I don't think that should be a explanation.