You have a data member pointer to two unrelated classes. Well, you can't find a common type that can hold both pointers. It will only work if the function parameter is a data member pointer to a member of the derived, because it's guaranteed to contain the member too, if a base contains it:
struct a { int c; }; struct b : a { }; int main() { int b::*d = &a::c; }
Update: I think i should write why the above converts from a::*
to b::*
implicitly. After all, we usually have b*
to a*
! Consider:
struct a { };
struct b : a { int c; };
struct e : a { };
int main() { int a::*d = &b::c; e e_; (e_.*d) = 10; /* oops! */ }
If the above would be valid, you would really much screw up. The above is not valid, because conversion from b::*
to a::*
is not implicit. As you see, we assigned a pointer to b::c, and then we could dereference it using a class that doesn't contain it at all! (e
). The compiler enforces this order:
int main() { int b::*d = &b::c; e e_; (e_.*d) = 10; /* bug! */ }
It fails to compile now, because e
is not derived from b
, the class the member pointer pointer belongs to. Good! The following, however, is very valid and compiles, of course (changed classes a
and b
):
struct a { int c; };
struct b : a { };
struct e : a { };
int main() { int e::*d = &a::c; e e_; (e_.*d) = 10; /* works! */ }
To make it work for your case, you have to make your function a template:
template<typename Class>
void DoThings (int Class::*arg) { /* do something with arg... */ }
Now, the compiler will auto-deduce the right class that the given member pointer belongs too. You will have to pass the instance alongside of the member pointer to actually make use of it:
template<typename Class>
void DoThings (Class & t, int Class::*arg) {
/* do something with arg... */
(t.*arg) = 10;
}
If you just want to set some member you already know at the time you write DoThings, the following suffices:
template<typename Class>
void DoThings (Class & t) {
t.c = 10;
}