Inheritance Implementation Issues
I. Virtual Methods
1. The first field of each object points to a virtual method table.
a. This table is often called a vtable.
b. Each entry in the table is the address of one of the virtual
methods in the object
c. The table does not contain the addresses of non-virtual methods,
since the addresses of these methods can be statically
inserted into the object code by the linker.
2. When the program calls a virtual method, the compiler inserts
code to lookup the address of the method in the object's
vtable and jump to that address
Example: The call f->m() will be translated to the following
code, assuming that m is the third method in the vtable:
r1 = f // load the address of f into register 1
r2 = *r1 // puts the address of the vtable into register 2
// since the vtable pointer is the first field in
// every object
r2 = *(r2 + 2*4) // assuming 4 = sizeof(address)--
// retrieves the contents of the third
// entry in the vtable, which is the
// address of m (assumes table is 0-indexed)
call *r2
3. The vtable for a derived class is created by:
a. Copying the vtable from the base class
b. Updating the vtable to point to any virtual methods that
the derived class redefines
c. Appending to the vtable the addresses of any additional
virtual methods that are defined by the derived class
This arrangement guarantees that the methods declared by the
base class will be found in the same place in both the base
class's and the derived class's vtables. This is why it does
not matter whether a variable declared as a pointer to the
base class actually contains a reference to an object of the
derived class type.
4. Reasons why virtual methods slow down a program's performance
a. The dynamic lookup process shown above requires at least two
more memory accesses than a static method call requires (the
loading of the address of f is required in both cases since
the address of f must be passed as the this argument.
b. The compiler often cannot inline a virtual method
i. inlining involves replacing a method call with the method's
body, thus eliminating the overhead of both a function
call and its return (calling and returning from a function
requires manipulating the stack).
ii. the compiler can only inline a method if it knows at compile
time which method will actually get called at run-time.
Virtual methods can be inlined provided the compiler can
determine the type of an object statically, but this
determination is often impossible.
Side notes:
1) The C++ compiler will automatically inline any method
that is defined in a .h file (i.e., whose implementation
is included in the .h file)
2) You can ask a C/C++ compiler to inline a function by
prefixing the function header with the inline
keyword:
inline int getBalance();
II. Object Layout
1. If the class contains any virtual methods, then the first field
will be a pointer to the vtable. If the object does not contain
any virtual methods, then there will be no virtual table and
the fields of the object will start at offset 0.
2. Next come the fields (i.e., instance variables) of the object.
3. A derived class appends its fields to the fields of its base
class. As with vtables, this appending process ensures that
the base class's instance variables can be found in the same
place in a derived object's record as in a base object's record.