Adding 1 or more virtual
methods to a class causes (in this case 1) an object instance of that class to contain a hidden pointer to a compiler-managed "virtual method table" (vtable) at the front of the object's memory, eg:
int *data = &a; A a;
data -> --------------------
| vtable | -> [0]: &A::f
| (8 bytes) |
|------------------|
data[2] -> | data[0]: 22 |
|------------------|
| data[1]: 33 |
--------------------
Assuming sizeof(int)
is 4 (which is usually the case), being able to access the object's data[0]
member via an int*
pointer to the object, where that pointer is indexing the 3rd int
, tells us that there is an extra 8 bytes present at the front of the object, which can be accounted for by the vtable pointer, if the code is being compiling as 64bit (if it were compiled as 32bit instead, the vtable pointer would be 4 bytes, and data[2]
would be accessing A::data[1] = 33
).
Without any virtual
methods, there is no vtable present, so the extra 8 bytes are not present, and thus indexing to the 3rd int
from the front of the object will exceed past the bounds of the object into surrounding memory, eg:
int *data = &a; A a;
data -> --------------------
| data[0]: 22 |
|------------------|
| data[1]: 33 |
--------------------
data[2] ->
1: this is an implementation detail of the compiler. The C++ standard doesn't dictate how virtual methods are to be implemented. Most compilers will use a vtable, though.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…