Programming Languages
Total Page:16
File Type:pdf, Size:1020Kb
◦ ◦◦◦ TECHNISCHE UNIVERSITAT¨ MUNCHEN¨ ◦◦◦◦ ◦ ◦ ◦◦◦ ◦◦◦◦ ¨ ¨ ◦ ◦◦ FAKULTAT FUR INFORMATIK Programming Languages Multiple Inheritance Dr. Axel Simon and Dr. Michael Petter Winter term 2012 Multiple Inheritance 1 / 29 Outline Inheritance Principles 1 Interface Inheritance 2 Implementation Inheritance 3 Liskov Substition Principle and Shapes C++ Object Heap Layout 1 Basics 2 Single-Inheritance Excursion: Linearization 3 Virtual Methods 1 Ambiguous common parents 2 Principles of Linearization C++ Multiple Parents Heap Layout 3 Linearization algorithm 1 Multiple-Inheritance 2 Virtual Methods 3 Common Parents Discussion & Learning Outcomes Multiple Inheritance 2 / 29 “Wouldn’t it be nice to inherit from several parents?” Multiple Inheritance Inheritance Principles 3 / 29 Interface vs. Implementation inheritance The classic motivation for inheritance is implementation inheritance Code reusage Child specializes parents, replacing particular methods with custom ones Parent acts as library of common behaviours Implemented in languages like C++ or Lisp Code sharing in interface inheritance inverts this relation Behaviour contract Child provides methods, with signatures predetermined by the parent Parent acts as generic code frame with room for customization Implemented in languages like Java or C# Multiple Inheritance Inheritance Principles 4 / 29 Interface Inheritance DropDownList refresh() ActionObserver MyDDL changed() changed() Multiple Inheritance Inheritance Principles 5 / 29 Implementation inheritance PowerShovel FrontLoader actuate() actuate() House actuate() Bulldozer Undercarriage moveTo(x,y) Tracks Wheels moveTo(x,y) moveTo(x,y) Multiple Inheritance Inheritance Principles 6 / 29 Excursion: LSP and Square-Rect-Problem The Liskov Substitution Principle Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it. class Rectangle{ Rectangle r= void setWidth(intw){ this.w=w;} new Square(2); void setHeight(inth){ this.h=h;} r.setWidth(3); void getWidth(){ returnw;} r.setHeight(4); void getHeight(){ returnh;} assertr.getHeight()* } r.getWidth()==12; class Square extends Rectangle{ ! Behavioural assumptions void setWidth(intw){ this.w=w;h=w;} void setHeight(inth){ this.h=h;w=h;} } Multiple Inheritance Inheritance Principles 7 / 29 “So how do we lay out objects in heap anyway?” Multiple Inheritance Standard Object Heap Layout 8 / 29 Object layout classA{ int a; int f(int); }; classB: publicA{ int b; int g(int); }; C classC: publicB{ int a int c; int h(int); int b }; int c ... C c; c.g(42); %c= alloca %class.C %1= getelementptr %c, i640, i320 %2= call i32 @_g(%1, i32 42) ; g is statically known Multiple Inheritance Standard Object Heap Layout Object layout & inheritance 9 / 29 Object layout – virtual methods classA{ int a; virtual int f(int); virtual int g(int); virtual int h(int); }; classB: publicA{ int b; int g(int); }; C classC: publicB{ vptr A::f int c; int h(int); int a B::g }; int b ... C::h int c C c; c.g(42); %c.vptr= getelementptr %c, i640, i640 ; select vptr-entry %1= load %c.vptr ; dereference vptr %2= getelementptr %1, i641 ; select g()-entry %3= load %2 ; dereference g()-entry %4= call i32 %3(%c, i32 42) Multiple Inheritance Standard Object Heap Layout Virtual Methods 10 / 29 “So how do we include several parent objects?” Multiple Inheritance Implementation of Multiple inheritance 11 / 29 Multiple Base Classes classA{ int a; int f(int); }; classB{ int b; int g(int); }; A int a B classC: publicA, publicB{ } int c; int h(int); B int b }; ... C int c C c; c.g(42); %c= alloca %class.C %1= getelementptr %c, i640, i321 ; select B-offset in C %2= call i32 @_g(%1, i32 42) ; g is statically known ! getelementptr hides the ∆B here! Multiple Inheritance Implementation of Multiple inheritance Multiple base classes in layout 12 / 29 Ambiguities classA{ void f(int); }; classB{ void f(int); }; classC: publicA, public B {}; C* pc; pc->f(42); ! Which method is called? Solution I: Explicit qualification Solution II: Automagical resolution pc->A::f(42); Idea: The Compiler introduces a pc->B::f(42); linear order on the nodes of the inheritance graph Multiple Inheritance Implementation of Multiple inheritance Ambiguities 13 / 29 Linearization Inheritance Relation H Multiplicity M Defined by ancestors. Defined by the order of multiple ancestors. Principles 1 An inheritance mechanism (maps Object to sequence of ancestors) must follow the inheritance partial order H 2 The inheritance is a uniform mechanism, and its searches (! total order) apply identically for all object properties (!fields/methods) 3 In any case the inheritance relation H overrides the multiplicity M 4 When there is no contradiction between multiplicity M and inheritance H, the inheritance search must follow the partial order H [ M. Multiple Inheritance Implementation of Multiple inheritance Linearization 14 / 29 Linearization algorithm candidates Depth-First Search W ABWC ! Principle 1 inheritance is violated B C A Breadth-First Search W ABCWD ! Principle 1 inheritance is violated D B C A Multiple Inheritance Implementation of Multiple inheritance Linearization 15 / 29 Linearization algorithm candidates Reverse Postorder Rightmost DFS W ABFDCEGHW G Linear extension of inheritance relation X D EF H B C A Reverse Postorder Rightmost DFS FG ABCDGEF ! But principle 4 multiplicity is violated! B D E C A Multiple Inheritance Implementation of Multiple inheritance Linearization 16 / 29 Linearization Algorithm Idea [Ducournau and Habib(1987)] Successively perform Reverse Postorder Rightmost DFS and refine inheritance graph G with contradiction arcs. The reservoir set of potential contradiction arcs CA is initially M, while the inheritance graph G starts from H. do 1 search RPDFSG 2 CA fcontradiction arcs of upper searchg \ M 3 G G [ CA; while (CA 6= ;) ^ (search violates H [M) Multiple Inheritance Implementation of Multiple inheritance Linearization 17 / 29 Linearization vs. explicit qualification Linearization Qualification No switch/duplexer code More flexible, fine-grained necessary Linearization choices may be No explicit naming of qualifiers awkward or unexpected Unique super reference Languages with automatic linearization exist CLOS Common Lisp Object System Prerequisite for ! Mixins Multiple Inheritance Implementation of Multiple inheritance Linearization 18 / 29 Virtual Tables for Multiple Inheritance classA{ int a; virtual int f(int); }; classB{ int b; virtual int f(int); virtual int g(int); vptr 0 B A RTTI }; } int a C::f classC: publicA, publicB{ vptr B int c; int f(int); B int b RTTI }; C::Bf ... C int c B::g C c; B* pb=&c; pb->f(42); %1= getelementptr %c, i640, i321, i640 ;select B-offset in C %2= load i32 %1 ;load vptr-entry %3= load i32 %2 ;load f()-thunk-entry %5= call i32 %3(%1, i32 42) Multiple Inheritance Implementation of Multiple inheritance Virtual Table 19 / 29 Virtual table A Virtual Table consists of different parts: 0 1 the constant offset of an objects heap RTTI representation to its parents heap C::f representation B RTTI 2 a pointer to a runtime type information C::Bf object (not relevant for us) B::g 3 method pointers of the overwritten methods for resolving virtual methods Several virtual tables are joined when multiple inheritance is used Casts! The vptr field in each object points at the beginning of the first virtual method pointer Multiple Inheritance Implementation of Multiple inheritance Virtual Table 20 / 29 Virtual table 2 Remarks: The virtual table is created at compile time and filled with offsets, virtual method pointers and thunks ∆B is the relative position of the B part in C, and known at compile time. This entry is primarily used for dynamic casts: C c; B*b=&c; void*v= dynamic_cast<void*>(b); printf("%d, %d, %d",&c,b,v); Multiple Inheritance Implementation of Multiple inheritance Virtual Table 21 / 29 Virtual table 3 Remarks: thunks are trampoline methods, delegating the virtual method to its original implementation with an adapted this-reference C c; B*b=&c; b->f(42); /* f(int) provided by C::f(int), addressing its variables relative to C */ B-in-C-virtual table entry for f(int) is the thunk _f(int), adding ∆B to the this parameter define i32 @__f(%this, i32 %i){ %1= getelementptr %this, i64 -1, i320, i320 %2= tail call i32 @_f(%1, i32 %i) ret i32 %2 } Multiple Inheritance Implementation of Multiple inheritance Virtual Table 22 / 29 “But what if there are common ancestors?” Multiple Inheritance Implementation of Multiple inheritance Virtual Table 23 / 29 Distinguished base classes classL{ int l; virtual void f(int); }; classA: publicL{ 0 int a; void f(int); RTTI vptr }; A::f L int l classB: publicL{ B B int b; void f(int); } A int a RTTI }; vptr B::f classC: publicA, publicB{ L int l int c; B int b }; ... C int c C c; L* pl=&c; pl->f(42); C* pc=(C*)pl; ! Ambiguity! L* pl=(A*)&c; C* pc=(C*)(A*)pl; Multiple Inheritance Implementation of Multiple inheritance Distinguished base classes 24 / 29 Common base classes classW{ W int w; virtual void f(int); 0 virtual void g(int); RTTI vptr A::f virtual void h(int); C::h }; A int a W- B classA: public virtualW{ vptr B int a; void f(int); RTTI B int b B::g }; W classB: public virtualW{ C int c RTTI int b; void g(int); A::Wf vptr }; B::Wg W int w classC: publicA, publicB{ C::Wh int c; void h(int); }; ! Offsets to virtual base ... ! Ambiguities C* pc; e.g. overwriting f in A and B pc->f(42); ! Casting! ((W*)pc)->h(42); W* pw=&c; ((A*)pc)->f(42); C* pc=(C*)pw; Multiple Inheritance Implementation of Multiple inheritance Common base classes 25 /