Me gustaría saber exactamente cómo se organizarán las clases en la memoria esp. con herencia y funciones virtuales.diseño de memoria de la clase heredada
Sé que esto no está definido por el estándar de lenguaje C++. Sin embargo, ¿hay alguna manera fácil de descubrir cómo su compilador específico implementará estos mediante la escritura de algún código de prueba?
EDIT: - El uso de algunas de las respuestas a continuación: -
#include <iostream>
using namespace std;
class A {
public:
int a;
virtual void func() {}
};
class B : public A {
public:
int b;
virtual void func() {}
};
class C {
public:
int c;
virtual void func() {}
};
class D : public A, public C {
public:
int d;
virtual void func() {}
};
class E : public C, public A {
public:
int e;
virtual void func() {}
};
class F : public A {
public:
int f;
virtual void func() {}
};
class G : public B, public F {
public:
int g;
virtual void func() {}
};
int main() {
A a; B b; C c; D d; E e; F f; G g;
cout<<"A: "<<(size_t)&a.a-(size_t)&a<<"\n";
cout<<"B: "<<(size_t)&b.a-(size_t)&b<<" "<<(size_t)&b.b-(size_t)&b<<"\n";
cout<<"C: "<<(size_t)&c.c-(size_t)&c<<"\n";
cout<<"D: "<<(size_t)&d.a-(size_t)&d<<" "<<(size_t)&d.c-(size_t)&d<<" "<<(size_t)&d.d- (size_t)&d<<"\n";
cout<<"E: "<<(size_t)&e.a-(size_t)&e<<" "<<(size_t)&e.c-(size_t)&e<<" "<<(size_t)&e.e- (size_t)&e<<"\n";
cout<<"F: "<<(size_t)&f.a-(size_t)&f<<" "<<(size_t)&f.f-(size_t)&f<<"\n";
cout<<"G: "<<(size_t)&g.B::a-(size_t)&g<<" "<<(size_t)&g.F::a-(size_t)&g<<" " <<(size_t)&g.b-(size_t)&g<<" "<<(size_t)&g.f-(size_t)&g<<" "<<(size_t)&g.g-(size_t)&g<<"\n";
}
Y la salida es: -
A: 8
B: 8 12
C: 8
D: 8 24 28
E: 24 8 28
F: 8 12
G: 8 24 12 28 32
Así que todas las clases tienen una v-PTR en loc 0 de tamaño 8 D tiene otro v-ptr en la ubicación 16. De manera similar, para E. G también parece tener un v-ptr a 16, aunque desde mi (limitado) entendimiento, habría supuesto que tendría más.
+1 Este código de ejemplo está más cerca de lo que se me ocurrió. Solo trata de evitar confiar en el diseño de la memoria. No hay garantía de que permanecerá igual en las versiones futuras de su compilador (o incluso en otros contextos con la misma versión del compilador, por ejemplo, la optimización). Apuesto que casi siempre hay una mejor manera de resolver el problema. – Andre
Gracias. Eso ayuda un poco. Combinando tu respuesta con la de Azza ... También me interesó lo que sucedería si tuviéramos clase A; clase B; clase C: público A, público B; Esto parece dar un resultado donde hay múltiples punteros vtable. Los miembros de datos de A parecen ser lo primero antes de B. – owagh
Nunca he tratado con herencias múltiples. Pero aún puedes intentarlo ver lo que muestran las compensaciones. Sinceramente, no tengo idea de cómo funciona la herencia múltiple debajo. – Mysticial