Sto leggendo questo articolo "Virtual method table"virtuale tavolo metodo per multiple-eredità
esempio nell'articolo di cui sopra:
class B1 {
public:
void f0() {}
virtual void f1() {}
int int_in_b1;
};
class B2 {
public:
virtual void f2() {}
int int_in_b2;
};
class D : public B1, public B2 {
public:
void d() {}
void f2() {} // override B2::f2()
int int_in_d;
};
B2 *b2 = new B2();
D *d = new D();
Nell'articolo, l'autore introduce che il layout di memoria dell'oggetto d
è il seguente:
d:
D* d--> +0: pointer to virtual method table of D (for B1)
+4: value of int_in_b1
B2* b2--> +8: pointer to virtual method table of D (for B2)
+12: value of int_in_b2
+16: value of int_in_d
Total size: 20 Bytes.
virtual method table of D (for B1):
+0: B1::f1() // B1::f1() is not overridden
virtual method table of D (for B2):
+0: D::f2() // B2::f2() is overridden by D::f2()
La domanda è circa d->f2()
. La chiamata a d->f2()
passa un puntatore B2
come puntatore this
quindi dobbiamo fare qualcosa di simile:
(*(*(d[+8]/*pointer to virtual method table of D (for B2)*/)[0]))(d+8) /* Call d->f2() */
Perché dovremmo passare un puntatore B2
come non puntatore this
il puntatore originale D
??? In realtà stiamo chiamando D :: f2(). Sulla base della mia comprensione, dovremmo passare un puntatore D
come this
alla funzione D :: f2().
___update____
Se passa un puntatore B2
come this
a D :: f2(), Che cosa succede se si vuole accedere ai membri B1
classe D :: f2() ?? Credo che il puntatore B2
(questo) è mostrato in questo modo:
d:
D* d--> +0: pointer to virtual method table of D (for B1)
+4: value of int_in_b1
B2* b2--> +8: pointer to virtual method table of D (for B2)
+12: value of int_in_b2
+16: value of int_in_d
Ha già un offset dell'indirizzo iniziale di questo layout memoria contigua certo. Ad esempio, vogliamo accedere a b1
all'interno di D :: f2(), credo in runtime, farà qualcosa di simile: *(this+4)
(this
punti allo stesso indirizzo di b2) che farebbe riferimento a b2
in B
????
(1) cosa intendi per "intercambiabile", puoi spiegare un po 'più in dettaglio? (2) Se si passa un puntatore 'B2' come' this' a D :: f2(), cosa succede se si vuole accedere ai membri della classe B1 in D :: f2()? Per (2), si prega di consultare l'aggiornamento della domanda. – Fihop
Grazie mille !! Per favore, verificamelo. 'B2 b2; b2.test() ', è un puntatore' B2' passato come 'this' a' B2 :: test() 'sicuramente poiché' b2' è un oggetto standlone. Per 'D d; d.test() ', il compilatore passa il puntatore di correzione che effettivamente punta all'oggetto secondario' B2' di 'D' come' this' a 'test()' dato che la funzione di chiamata effettiva è 'B2 :: test() '. Se 'questo' non punta a' B2' all'interno di 'D', causerebbe problemi quando si accede ai membri di' B2' all'interno della funzione 'B2 :: test()'. Questo è il motivo per cui penso che dovremmo passare un puntatore di correzione come "questo". Questo esempio non può spiegare l'aggiornamento. Grazie ancora – Fihop
Per 'D d; d.test() ', sono d'accordo che facciamo qualcosa come' d.test (B2 * b2) '(significa che' this' punta al sotto-oggetto 'B2' di D). Tuttavia, all'interno di 'B2: test',' b2-> f2() 'dovrebbe eseguire' D :: f2'. Ho ragione? Ora il problema diventa che tipo di 'this' è passato a' b2-> f2() ' – Fihop