您有一个指向两个不相关类的数据成员指针。好吧,您找不到可以同时保存两个指针的通用类型。它仅在函数参数是指向派生成员的数据成员指针时才有效,因为如果基包含它,它也保证包含该成员:
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::*
toa::*
的转换不是隐式的。如您所见,我们分配了一个指向 b::c 的指针,然后我们可以使用一个根本不包含它的类来取消引用它!( 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;
}