In the case of virtual functions, an additional member is inserted into the class: a pointer to the virtual table, or _vptr. The _vptr holds the address of a static table of function pointers. The exact position of the _vptr among the class’ data members is implementation-dependent. Traditionally, it was placed after the user-declared data members. However, some compilers (Visual C++, for instance) have moved it to the beginning of the class for performance reasons. Theoretically, the _vptr can be located anywhere inside the class–even among user-declared members. Consider:
class PolyDate { public: int day; int month; int year; Date(); virtual ~Date(); //polymorphic bool isLeap() const; bool operator == (const Date& other); };
Defining a C struct that corresponds to the binary representation of a PolyDate object is more precarious in this case and requires intimate acquaintance with the compiler’s preferred position of the _vptr as well as with its size. Such a C struct might look like this code on some implementations:
struct POD_Date { int day; int month; int year; void * do_not_touch; /* the _vptr */ };
However, on other implementations (Visual C++, for instance) it might look like this:
struct POD_Date { void * do_not_touch; /* the _vptr */ int day; int month; int year; void * do_not_touch; // };
Another hazard here is that the value of the _vptr is transient, which means that it might have a different value, according to the address space of the process that executes the program. Consequently, when an entire polymorphic object is stored in a file and retrieved later, the retrieved data cannot be used as a valid object. For all these reasons, accessing polymorphic objects from C code is dangerous and generally needs to be avoided.