How to gain Access to member variables of a class using void pointer but Not Object

后端 未结 6 1089
暖寄归人
暖寄归人 2021-01-24 21:29

I am trying to access member variables of a class without using object. please let me know how to go about.

class TestMem
{
    int a;
    int b;
public:
    Tes         


        
相关标签:
6条回答
  • 2021-01-24 22:05

    There totally is a way. C++ has member pointers, pointers relative to an object. They are defined by prefixing T:: to the * on the pointer type, and used by using the ->* or .* member pointer access operators. So yeah, it looks horrible :).

    class T {
        int a, b;
    public:
        typedef int T::* T_mem_ptr_to_int;
    
        static T_mem_ptr_to_int const a_ptr;
        static T_mem_ptr_to_int const b_ptr;
    };
    
    T::T_mem_ptr_to_int const T::a_ptr = &T::a;
    T::T_mem_ptr_to_int const T::b_ptr = &T::b;
    
    int weird_add(T* left, T* right) {
        return left->*T::a_ptr + right->*T::b_ptr;
    }
    

    This is used much more often for member function pointers, which look like Result (T::*ptr_name)(Arg1, Arg2, ...).

    0 讨论(0)
  • 2021-01-24 22:06

    Short answer: You can't.

    Long answer: You can, but it's highly implementation dependent. If you dump the memory you find at *p you'll see, somewhere around there, what you're looking for - a and b. But you will very likely also see some other stuff. What that stuff is, what it means, how big it is (and by implication where a and b actually live) is implementation dependent.

    0 讨论(0)
  • 2021-01-24 22:09

    Simple answer: Don't do it.

    There just can not be any situation where you can justify accessing like this. There just has to be a different solution.

    0 讨论(0)
  • 2021-01-24 22:17

    I wanted to comment the answer provided by John Kugelman, being a new member didn't have enough reputation, hence posting it like an answer.

    offsetof - is a C function used with structures where every member is a public, not sure whether we can refer the private variables as referred in the answer.

    However the same can be achieved replacing the offsetof with a simple sizeof, ofcourse when we are sure of the type of the data members.

    int vala = *reinterpret_cast<int *>(reinterpret_cast<char *>( ptr ) );
    int valb = *reinterpret_cast<int *>(reinterpret_cast<char *>( ptr ) + sizeof ( int ) );
    

    To my knowledge, you wouldn't be able to access. By the time you have assigned p, it doesn't refer to o1 here and p cannot replace pMem in (o1.*pMem)(), as p is not defined as function member to TestMem.

    0 讨论(0)
  • 2021-01-24 22:18

    I came up with a solution but it's dirty:

    class TestMem
    {
    public:
        int a;
        int b;
        TestMem(){}
        void TestMem1()
        {
            a = 10;
            b = 20;
        }
    };
    
    void* offset(void* ptr, ...)
    {
      va_list ap;
      va_start(ap, ptr); // get 1st argument's address
    
      long i = va_arg(ap, long); // get next argument
      va_end(ap);
    
      return (char*)ptr + i;
    }
    
    void test()
    {
      TestMem t;
      void* p = (TestMem*)&t;
      t.a = 8;
      t.b = 9;
      printf("%i\n", *(int*)offset(p, &TestMem::a));
      printf("%i\n", *(int*)offset(p, &TestMem::b));
    }
    
    0 讨论(0)
  • 2021-01-24 22:19

    The "right" way to do this is by using the offsetof() macro from <stddef.h>. Unfortunately offsetof() has some fairly draconian restrictions in C++:

    Because of the extended functionality of structs in C++, in this language, the use of offsetof is restricted to "POD [plain old data] types", which for classes, more or less corresponds to the C concept of struct (although non-derived classes with only public non-virtual member functions and with no constructor and/or destructor would also qualify as POD).

    So if you make a and b public and get rid of TestMem's constructor, you can write something like this to access a:

    C++ style:

    #include <cstddef>
    
    int vala = *reinterpret_cast<int *>(reinterpret_cast<char *>(&o1)
               + offsetof(TestMem, a));
    

    C style:

    #include <stddef.h>
    
    int vala = *(int *) ((char *) &o1 + offsetof(TestMem, a));
    

    Notice that you need to use &o1 here, not p, which is a function pointer. The address of TestMem::TestMem1 won't have any relation to the locations of a and b. Class methods don't reside in memory anywhere near class member variables.


    The "wrong" way is to just guess at where a and b are in memory. Most likely they are at offsets 0 and 4 from the start of o1, respectively. So this code would work most of the time:

    int vala = *(int *) ((char *) &o1 + 0);
    int valb = *(int *) ((char *) &o1 + 4);
    

    There are a lot of assumptions here. This assumes that ints are 4 bytes and that there's no padding between a and b. On the other hand it doesn't have any of the restrictions from above: a and b don't need to be public, you can have a constructor, whatever.

    0 讨论(0)
提交回复
热议问题