您有一个指向两个不相关的类的数据成员指针。好吧,您找不到可以容纳两个指针的通用类型。仅当函数参数是指向派生成员的数据成员指针时,它才有效,因为如果基类包含该成员,则保证也包含该成员:
struct a { int c; }; struct b : a { }; int main() { int b::*d = &a::c; }
Update:我想我应该写为什么上面的转换a::*
to b::*
隐含地。毕竟我们平时都有b*
to a*
!考虑:
struct a { };
struct b : a { int c; };
struct e : a { };
int main() { int a::*d = &b::c; e e_; (e_.*d) = 10; /* oops! */ }
如果上述内容是有效的,那你就真的搞砸了。以上是not有效,因为转换自b::*
to a::*
不是隐式的。正如你所看到的,我们分配了一个指向 b::c 的指针,然后我们可以使用一个根本不包含它的类来取消引用它! (e
)。编译器强制执行此顺序:
int main() { int b::*d = &b::c; e e_; (e_.*d) = 10; /* bug! */ }
It fails现在编译,因为e
不是源自b
,成员指针指针所属的类。好的!然而,以下内容是非常有效的并且当然可以编译(更改了类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! */ }
为了使其适合您的情况,您必须将您的函数设为模板:
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;
}