In a previous post, I discussed how any pointer can be cast to a defined structure in order to have access to private members. The question now is how this works when inheritance is involved.
First, define a series of classes for composition and inheritance.
#include <stdio.h>
#include <vector>
class ElementClass {
private:
double r = 8.1;
std::vector<int> vect1{ 10, 20, 30, 5, 1 };
double m = 7.4;
};
class BaseClass {
private:
int i = 4;
ElementClass c;
};
class BaseClass2 {
private:
double r2 = 7.1;
double m2 = 6.7;
std::vector<int> vect2{ 3, 14, 15, 92 };
};
class DerivedClass : BaseClass, BaseClass2 {
private:
double d = 9.8;
};
It is expected that precedence will take place as follows:
- First base class
- Members of first base class
- Second base class
- Members of second base class
- Derived class
- Members of derived class
Based on the code above, we assume the sequential layout of the derived class to be as follows.
struct DerivedClass_def {
// BaseClass
int i;
// ElementClass
double r;
std::vector<int> vect1;
double m;
// BaseClass2
double r2;
double m2;
std::vector<int> vect2;
// DerivedClass
double d;
};
This can be tested by casting the pointer and inspecting the members.
int main()
{
DerivedClass* d = new DerivedClass();
DerivedClass_def* df = (DerivedClass_def*)d;
printf("i = %d\n", df->i);
printf("r = %.1f\n", df->r);
printf("m = %.1f\n", df->m);
printf("vect1.size = %d\n", df->vect1.size());
printf("vect1 = {");
if (df->vect1.size()>0){
printf("%d", df->vect1[0]);
}
for (int n = 1; n < df->vect1.size(); n++){
printf(", %d", df->vect1[n]);
}
printf("};\n");
printf("r2 = %.1f\n", df->r2);
printf("m2 = %.1f\n", df->m2);
printf("vect2.size = %d\n", df->vect2.size());
printf("vect2 = {");
if (df->vect2.size()>0){
printf("%d", df->vect2[0]);
}
for (int n = 1; n < df->vect2.size(); n++){
printf(", %d", df->vect2[n]);
}
printf("};\n");
printf("d = %.1f\n", df->d);
delete d;
d = NULL;
return 0;
}
Running the code gives the following output.
i = 4
r = 8.1
m = 7.4
vect1.size = 5
vect1 = {10, 20, 30, 5, 1};
r2 = 7.1
m2 = 6.7
vect2.size = 4
vect2 = {3, 14, 15, 92};
d = 9.8
It is seen that the code successfully displays the content of the derived class, and all base classes. Memory layout (in this case) is guaranteed.
What's next? You can try this yourself.