2つの無関係なクラスへのデータメンバーポインタがあります。さて、両方のポインタを保持できる共通の型を見つけることはできません。これは、関数パラメーターが派生のメンバーへのデータメンバーポインターである場合にのみ機能します。これは、ベースにメンバーが含まれている場合、メンバーも含まれることが保証されているためです。
struct a { int c; }; struct b : a { }; int main() { int b::*d = &a::c; }
更新:上記が暗黙的にからa::*
に変換される理由を書く必要があると思います。b::*
結局のところ、私たちは通常しなければb*
なりませa*
ん!検討:
struct a { };
struct b : a { int c; };
struct e : a { };
int main() { int a::*d = &b::c; e e_; (e_.*d) = 10; /* oops! */ }
上記が有効であるならば、あなたは本当に多くの失敗をするでしょう。からへの変換は暗黙的ではないため、上記は無効です。ご覧のとおり、b :: cへのポインターを割り当てた後、それをまったく含まないクラスを使用して、ポインターを逆参照することができます。()。コンパイラーはこの順序を強制します:b::*
a::*
e
int main() { int b::*d = &b::c; e e_; (e_.*d) = 10; /* bug! */ }
メンバーポインタポインタが属するクラスから派生していないため、コンパイルに失敗します。良い!ただし、以下は非常に有効であり、もちろんコンパイルされます(変更されたクラスと):e
b
a
b
struct a { int c; };
struct b : a { };
struct e : a { };
int main() { int e::*d = &a::c; e e_; (e_.*d) = 10; /* works! */ }
ケースで機能させるには、関数をテンプレートにする必要があります。
template<typename Class>
void DoThings (int Class::*arg) { /* do something with arg... */ }
これで、コンパイラは、指定されたメンバーポインタも属する正しいクラスを自動推測します。実際にインスタンスを使用するには、メンバーポインタと一緒にインスタンスを渡す必要があります。
template<typename Class>
void DoThings (Class & t, int Class::*arg) {
/* do something with arg... */
(t.*arg) = 10;
}
DoThingsを作成するときにすでに知っているメンバーを設定したいだけの場合は、次のようにすれば十分です。
template<typename Class>
void DoThings (Class & t) {
t.c = 10;
}