在C ++中确定成员的类实例

时间:2011-05-13 21:04:58

标签: c++

我从未在任何语言中看过这个,但我想知道这是否可能使用我不知道的一些技巧。

假设我有一个类似

的功能
struct A {
  // some members and methods ...
  some_t t;
  // more members ...
};   


void test(some_t& x) { // a reference to avoid copying a new some_t
    // obtain the A instance if x is the t member of an A 
    // or throw an error if x is not the t member of an A
    ...
    // do something
}

是否有可能获得A成员tx的实例?

7 个答案:

答案 0 :(得分:5)

不幸的是,这是不可能的。

答案 1 :(得分:4)

如果您知道自己引用了某个t实例的A成员,则可以使用container_of获取该实例,例如A* pa = container_of(&x, A, t);

当且仅当A具有虚拟成员时,验证结果指针实际上是A是否可行,遗憾的是,没有便携式方法可以检查。

但是,您可以使用多重继承和dynamic_cast来实现类似的功能,这允许在子对象之间进行交叉投射。

答案 2 :(得分:1)

您可以在A内添加指向some_t的指针(当然,如果some_tstructclass

像这样:

struct some_t
{
  A *a;
  ...
};

void test(some_t& x) 
{
  if( x.a )
  {
    // do some
  }
  else
    throw ...
}

答案 3 :(得分:1)

这个答案不符合原始问题的所有要求,我已将其删除,但OP要求我发布。它显示了在非常特定的条件下如何从指向成员变量的指针计算实例指针。

不应该,但你可以:

#include <iostream>
#include <cstddef>

using namespace std;

struct A
{
    int x;
    int y;
};

struct A* find_A_ptr_from_y(int* y)
{
    int o = offsetof(struct A, y);
    return (struct A*)((char *)y - o);
}

int main(int argc, const char* argv[])
{
    struct A a1;
    struct A* a2 = new struct A;

    cout << "Address of a1 is " << &a1 << endl;
    cout << "Address of a2 is " << a2 << endl;

    struct A *pa1 = find_A_ptr_from_y(&a1.y);
    struct A *pa2 = find_A_ptr_from_y(&(a2->y));

    cout << "Address of a1 (recovered) is " << pa1 << endl;
    cout << "Address of a2 (recovered) is " << pa2 << endl;
}

输出

Address of a1 is 0x7fff5fbff9d0
Address of a2 is 0x100100080
Address of a1 (recovered) is 0x7fff5fbff9d0
Address of a2 (recovered) is 0x100100080

警告:如果你传递给find_A_ptr_from_y的东西不是指向(结构A)的指针。你就会得到完全垃圾。

你应该(几乎)永远不要这样做。请参阅下面的DasBoot评论。

答案 4 :(得分:1)

如果你可以修改struct A及其构造函数,而 if 你可以确保结构打包,你可以在t之后直接添加一个值来保存一些魔术键。< / p>

struct A {
  ...
  some_t t
  struct magic_t
  { 
    uint32 code
    some_t* pt;
  } magic;
}
#define MAGICCODE 0xC0DEC0DE //or something else unique 

在A的构造函数中,执行:       this->magic.code = MAGICCODE; this->magic.pt = &(this->t);
然后你可以写

bool test(some_t *t)  //note `*` not `&`
{
    struct magic_t* pm = (struct magic_t*)(t+1);
    return (pm->pt == t && pm->code == MAGICCODE);
}

答案 5 :(得分:0)

我不太清楚你要做什么,但如果你想知道指向A成员的指针时想要找到结构A实例的指针,你可以这样做。

例如,参见linux内核中的c ontainer_of宏。

答案 6 :(得分:0)

函数x的参数test()无需成为任何类的成员,只要test()收敛即可。

如果特定应用程序x中的语义必须始终是类的成员,则可以通过传递其他paraemter或让some_t本身包含此类信息来提供该信息。但是要做到这一点将是不必要的,因为如果test()真的需要访问包含x的对象,那么为什么不简单地传递父对象呢?或者只是让test()成为同一个类的成员函数并且不传递任何参数?如果原因是因为x可能属于不同的类,那么可以使用多态来解决该问题。

基本上我建议你不会需要这样一种无法以更简单,更安全和更面向对象的方式解决的能力。