我的应用程序中的代码与此类似:
class A
{
public: int b;
}
class C
{
public: int d;
}
void DoThings (void *arg1, MYSTERYTYPE arg2);
A obj_a;
C obj_c;
DoThings(&obj_a, &A::b);
DoThings(&obj_c, &C::d);
问题是 - MYSTERYTYPE应该是什么?尽管如果你通过printf输出它并且打印出来的价值& A :: b就好了,那么无论是*还是int都没有工作。
澄清:是的,& A :: b是在C ++下定义的。是的,我正试图获得班级成员的抵消。是的,我很狡猾。
编辑:哦,我可以使用offsetof()。不管怎样,谢谢。
答案 0 :(得分:6)
您有一个指向两个不相关类的数据成员指针。好吧,你找不到一个可以同时拥有两个指针的常见类型。它只有在函数参数是指向派生成员的数据成员指针时才有效,因为它保证包含成员,如果基数包含它:
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::*
到a::*
的转换不是隐含的。如您所见,我们分配了一个指向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;
}
答案 1 :(得分:2)
您是否只是尝试使用恰好位于A
或C
对象内的整数的地址来调用函数?在这种情况下,Jeff McGlynn的回答是要走的路。
否则,如果你真的想要做一些棘手的事情,需要C ++的奇怪的指针到成员设施(你几乎肯定不是):
由于类A
和C
不相关,因此您需要一个模板函数来处理这两个:
template <typename T>
void DoThings(int T::*x);
如果C
实际上来自A
,则可以使用以下内容:
void DoThings(int A::*x);
答案 2 :(得分:0)
&amp; A :: b和&amp; C :: d是荒谬的,没有相关联的地址。您是否想要获得会员的抵消?
您确定不想要以下内容吗?
DoSomething(&obj_a,&obj_a.b);
答案 3 :(得分:0)
如果您使用模板作为j_random_hacker建议,并且编译器知道您调用函数的每个类的类型,则问题的字面答案为“template <typename CLASS> void DoThings (CLASS * object, int CLASS::*MEMBER)
”。
以下是它如何适合您的示例:
#include <iostream>
class A {
public:
int b;
};
class C {
public:
int d;
};
template <typename CLASS>
void DoThings (CLASS * object, int CLASS::*MEMBER)
{
std::cout << object->*MEMBER << std::endl;
}
A obj_a = { 2 };
C obj_c = { 4 };
int main (int argc, const char * argv[])
{
DoThings(&obj_a, &A::b);
DoThings(&obj_c, &C::d);
return 0;
}