Si j'étudie cette version dérivée de g ++
class X: public A, public B {
unsigned magic;
public:
X() : magic(0xcafebabe) {};
virtual void func(){ var = 1; } int var;
};
extern "C" int main()
{
X * x = new X; // from what I know, x have 2 vtables, is this the same in c#?
A * a = (A*)x; // &a == &x
B * b = (B*)x; // here &b != &x, so when calling b->func(), how is the address of var correct?
printf("%p -- %p -- %p\n", x, a, b);
unsigned* p = (unsigned*)((void*) x);
unsigned *q = (unsigned*)(p[1]);
printf("x=[%x %x %x %x]\n",p[0],p[1],p[2],p[3]);
p = (unsigned*)(p[0]);
printf("a=[%x %x %x %x]\n",p[0],p[1],p[2],p[3]);
printf("b=[%x %x %x %x]\n",q[0],q[1],q[2],q[3]);
}
Il se trouve que, dans de C de b == a + 1, de sorte que la structure de X est [vtable-X + A] [vtable-B ] [magic] [var] En examinant plus profond (nm ./a.out), vtable-X + a contient la référence vers X :: func (comme on pourrait s'y attendre). Lorsque vous avez casté votre X dans B, il a ajusté les pointeurs de sorte que les fonctions VTBL pour B apparaissent là où le code l'attend.
Aviez-vous l'intention de "cacher" B :: func()?
Le vtbl de B ressemble à une référence vers un "trampoline" à X qui restitue le pointeur d'objet à un X complet avant d'appeler la fonction X "régulière" que X + A vtbl contient.
080487ea <_ZThn8_N1X4funcEv>: # in "X-B vtbl"
_ZThn8_N1X4funcEv():
80487ea: 83 44 24 04 f8 addl $0xfffffff8,0x4(%esp)
80487ef: eb 01 jmp 80487f2 <_ZN1X4funcEv>
80487f1: 90 nop
080487f2 <_ZN1X4funcEv>: # in X-A vtbl
_ZN1X4funcEv():
80487f2: 55 push %ebp
80487f3: 89 e5 mov %esp,%ebp
80487f5: 8b 45 08 mov 0x8(%ebp),%eax
80487f8: c7 40 14 01 00 00 00 movl $0x1,0x14(%eax)
80487ff: 5d pop %ebp
8048800: c3 ret
Je suppose que vous voulez dire 'a == x' et' b! = X'. Puisque les pointeurs sont alloués les uns après les autres sur la pile, ils ont tous une adresse distincte ... bien qu'ils devraient tous pointer vers le même objet. – PypeBros
bien sûr, mon erreur :) Il est maintenant fixé, j'ai oublié que a == b compare les adresses – chris