This is my code. I just want to have a look at the memory layout of virtual inherit.
#include<iostream>
using namespace std;
class A{
private:
int a;
public:
virtual void print() const{
cout << a << endl;
}
};
class B:public virtual A{
private:
int b;
public:
void print() const{
cout << b << endl;
}
};
int main(){
A a;
B b;
return 0;
}
Then in gdb, I used
p a
p b
The output is
(gdb) p a
$1 = {
_vptr.A = 0x400b40 <vtable for A+16>,
a = 0
}
(gdb) p b
$2 = {
<A> = {
_vptr.A = 0x400b18 <vtable for B+56>,
a = 4196384
},
members of B:
_vptr.B = 0x400af8 <vtable for B+24>,
b = 0
}
(gdb)
I know the meaning of _vptr.A and _vptr.B but I don't understand the what does vtable for B+24 or A+16 mean.
Thanks for the answer!
The listing for a
says that it's a class with two fields: a vptr that points to a byte with offset 16 inside the vtable for A and a data element a
containing zero.
The second is along the same lines but more complicated due to the virtual base class. It's saying b consists of 3 fields: an instance of A with fields similar to those above, and then the two elements of B, again as above. This time the vptr is directed at offset 24.
Why does the vptr point into the middle of the table rather than its start? You'd have to know more about the details of gcc memory layout to say, and I don't. It's possible the initial bytes are RTTI (run time type information) and the given offset is the first element of the array of virtual function pointers. There are uncountably many other options.
NB. There is some good information in this earlier article saying there are always 2 pointers leading the vtable: one for the multiple inheritance top pointer and another for RTTI. If your machine and compiler are 64 bits (you really should mention this; it's important), this coincides with 16 bytes of pointers. B could be 24 bytes because there's an extra pointer to access the virtual base class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With