2

我的应用程序中有类似的代码:

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 应该是什么?void* 和 int 都不起作用,尽管如果通过 printf 输出值 &A::b 就可以正常打印。

澄清:是的,&A::b 是在 C++ 下定义的。是的,我正在尝试将偏移量分配给班级成员。是的,我很棘手。

编辑:哦,我可以使用 offsetof()。不管怎么说,还是要谢谢你。

4

4 回答 4

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::*toa::*的转换不是隐式的。如您所见,我们分配了一个指向 b::c 的指针,然后我们可以使用一个根本不包含它的类来取消引用它!( e)。编译器强制执行此顺序:

int main() { int b::*d = &b::c; e e_; (e_.*d) = 10; /* bug! */ }

它现在无法编译,因为e它不是从b成员指针指针所属的类派生的。好的!但是,以下内容非常有效并且可以编译,当然(更改了类ab):

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;
}
于 2009-01-07T15:48:19.480 回答
2

您是否只是尝试使用恰好存在于对象AC对象中的整数地址调用函数?在这种情况下,Jeff McGlynn 的答案就是要走的路。

否则,如果你真的想要做一些需要 C++ 奇怪的指向成员的工具的棘手事情(而且你几乎可以肯定不是):

由于类AC不相关,您将需要一个模板函数来处理两者:

template <typename T>
void DoThings(int T::*x);

如果C实际上是从 派生的A,则以下将起作用:

void DoThings(int A::*x);
于 2009-01-07T15:44:52.467 回答
0

&A::b 和 &C::d 是无意义的,没有关联的地址。您是否正在尝试获取成员的偏移量?

你确定你不想要类似下面的东西吗?

DoSomething(&obj_a,&obj_a.b);
于 2009-01-07T16:22:18.757 回答
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;
}
于 2011-05-05T14:47:45.107 回答