开发者

Determine class instance of a member in C++

I've never seen this in any language, but I was wondering if this is possible using some trick that I don't know.

Let's say that I have a function like

struct A {
  // some members and methods ...
  some_t t;
  // more members ...开发者_如何学JAVA
};   


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
}

Would it be possible to obtain the instance of A whose member t is x ?


No unfortunately it's not possible.


If you know that you have a reference to the t member of some A instance, you can get the instance using container_of, e.g. A* pa = container_of(&x, A, t);.

Verifying that the resulting pointer actually is an A is technically possible if and only if A has virtual members, unfortunately there's no portable method to check.

You can achieve something similar, however, using multiple inheritance and dynamic_cast, which allows cross-casting between subobjects.


You can add pointer to A inside some_t (of course if some_t is struct or class)

like this:

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

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


If you can modify struct A and its constructor and if you can ensure the structure packing, you can add a value directly after t which holds some magic key.

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

In A's constructor, do: this->magic.code = MAGICCODE; this->magic.pt = &(this->t);
Then you can write

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


This answer does not meet all the requirements of the original question, I had deleted it, but the OP requested I post it. It shows how under very specific conditions you can calculate the instance pointer from a pointer to a member variable.

You shouldn't, but you can:

#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;
}

Output

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

Caveats: if what you pass to find_A_ptr_from_y is not a pointer to (struct A).y you well get total rubbish.

You should (almost) never do this. See comment by DasBoot below.


It's not quite clear to me what you are trying to do, but if you are want to find the pointer to an instance of struct A when you know the pointer to a member of A, you can do that.

See for example the container_of macro in the linux kernel.


The parameter x of function test() need not be a member of any class as far as test() is converned.

If semantically in a particular application x must always be a member of a class then that information could be provided, either by passing an additional paraemter or having some_t itself contain such information. However to do that would be enturely unnecessary since if test() truely needed access to the object containing x, then why not simply pass the parent object itself? Or just make test() a member function of the same class and pass no paraemeters whatsoever? If the reason is because x may belong to differnt classes, then polymorphism can be employed to resolve that issue.

Basically I suggest that there is no situation where you would need such a capability that cannot be solved in a simpler, safer and more object oriented manner.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜