weird pointer problem

Hi,
Here's my code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>

struct BASE{
    int a;
};

struct PARENT:public BASE{
    virtual void Func()=0;
};

struct CHILD:public PARENT{
    void Func(){
        void *v=this;
        BASE *b1,*b2;
        b1=(BASE*)v;
        b2=this;
        std::cout<<b1->a<<std::endl
            <<b2->a<<std::endl;
    }
};

int main(){
    CHILD c;
    c.a=10;
    c.Func();
    std::cin.get();
    return 0;
}

It doesn't work.
Somehow b1 and b2 point to different locations.
I have no idea what's wrong. Please help.
It is indeed working correctly. The reason for the difference in pointer values has to do with
how the compiler implements inheritance and polymorphism.
Problem line is
 
void *v=this;

You shouldn't assign this pointer to a void pointer.
I still don't get it.
How does the compiler implement inheritance and polymorphism?
How could such implementation be useful?
How could I avoid such problem? (I allready did it by using a BASE* ,but I want to know if there's a way to keep the pointer void)

@Dufresne
I can do the same thing in main() with &c instead of this. It doesn't make any difference.
Did you mean that I should avoid void*?
Using void pointer should make difference in main. Assigning an object pointer to a void pointer and assigning this pointer to a void pointer is different.
If you assign this pointer to a void pointer , (in your example) , value of "a" will be lost.
But , if you assign object pointer to a void pointer , value of "a" will be keeped.


C++ Tutorial - important notes on this pointer:
this pointer stores the address of the class instance, to enable pointer access of the members to the member functions of the class.
this pointer is not counted for calculating the size of the object.
this pointers are not accessible for static member functions.
this pointers are not modifiable.
1
2
3
4
5
6
7
CHILD c;
void *vptr = &c ;
c.a=10;
c.Func();
CHILD *newChild = (CHILD*)vptr ;
newChild->Func();
std::cin.get();

this one works.
Last edited on
1
2
3
4
5
6
CHILD c;
c.a=10;
void *v=&c;
BASE* b1=(BASE*)v;
BASE* b2=&c;
return b1==b2;

This one doesn't.

CHILD *newChild = (CHILD*)vptr ;works
BASE* newBase = (CHILD*)vptr ;works
BASE* newBase = (BASE*)vptr ;fails
When a class/struct contains at least one virtual function or a virtual destructor, every instance of the class/struct contains, as its first data member, an implicit "vtable" pointer, or virtual table pointer. This
pointer is a pointer to a table (array) of member function pointers. The member function (pointers) in
this table are the virtual functions in the class/struct.

So when you instantiate CHILD in main, there are 8 bytes of memory allocated (assuming 32-bit):
the first four are the vtable pointer and the last four are the variable "a". "this" is a pointer to "a"
as implemented by the compiler (I do not know if the standard mandates this; however I did
reproduce your results using gcc). When you cast "this" to a void*, you get a pointer to the
eight-byte block, the first four of which is the vtable pointer. In short, the cast to void* causes
the compiler to subtract 4 bytes from the "this" pointer.

When you cast from void* back to BASE*, it does not add 4 back to the pointer. Again, I don't know
if this behavior is mandated by the standard or if this is implementation-defined.

Therefore, your b1 pointer is actually 4 bytes less than b2, and the result of which is accessing
the first four bytes of b1 accesses the vtable pointer and not a. So you are in fact printing out
the address of the vtable.

Topic archived. No new replies allowed.