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.