1 / 23

Multiple Inheritance for C++

Multiple Inheritance for C++. By Bjarne Stroustrup AT & T Bell Labs Murray Hill, NJ. PS_Coordinate { <List of ops> double x_; … };. PS_Point { <List of ops> PS_Coordinate pt_; };. Motivation for Multiple Inheritance. UG_Display { <List of ops> UG_Color color_;

adamdaniel
Download Presentation

Multiple Inheritance for C++

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Multiple Inheritance for C++ By Bjarne Stroustrup AT & T Bell Labs Murray Hill, NJ

  2. PS_Coordinate { <List of ops> double x_; … }; PS_Point { <List of ops> PS_Coordinate pt_; }; Motivation for Multiple Inheritance UG_Display { <List of ops> UG_Color color_; UG_Layer layer_; UG_Width width_; }; PS_Spline {..}; PS_Bspline {…}; PS_Bcurve {..}; PS_Line { <List of ops> PS_Coordinate start_; PS_Coordinate end_; }; UG_AdDisplay{..}; • PS_* and UG_* are from different modules • The display properties are added to the CAD geometry for visualization and translation • Geometry used for operations like CAM, FEA etc.

  3. Goals • A brief history of MI in C++ • Myths, the need for this presentation. • How MI is to be implemented for different use cases • Controversies that surrounded MI – follows from the Myths • Actual overheads and conclusion

  4. Multiple Inheritance • Representation of various widgets in a windowing system. • Representation of various processors and architectures for a multi-machine. Multi-environment debugger • Allows combination of independent concepts into a composite concept. • N concepts can be married to M concepts in N+M ways using MI • To achieve the same thing we need N+M+N*M classes with duplication.

  5. Some History • Made its appearance in Release 2.0 of Cfront • Bjarne considers having MI in Release 2.0 was a mistake • Not as important as parameterized types and exception handling • Reasons for implementing in 2.0 • Fitted very well in to C++ type system • Could be implemented within Cfront • Considered to be difficult to implement • Brad Cox says impossible

  6. Some History • Solution conceived in 1984 with Stein Krogdal of Simula • Solution similar to Ole-Johan Dahl considered in 1966. • Solution rejected because it would have complicated the GC. • BS later mentions “Fashion affected the sequence of events”

  7. Myths • Complicates Programming Language significantly • Is hard to implement • Expensive to run • Are the above really true?

  8. C++ Object Model class 2dpoint { float x, y; int translate (const 2dpoint *); }; float y • Static data members outside the class • Static and non static function members outside the class object • Non-static data members within the object float x 2dpoint *pt; pt->translate (…);= f__F12dpoint (pt,…) • Based on the Simple Model • Optimized for time and space overhead. • Table driven model is not efficient

  9. Object Model with Single Inheritance class 3dpoint: 2dpoint { float z; int translate (const 3dpoint *); }; float z float y float x 3dpoint *pt; pt->translate (3dpoint *);= f__F23dpoint (pt, 3dpoint *) 3dpoint *pt; pt->translate (2dpoint *);= f__F13dpoint (pt, 2doint *);

  10. Inheritance with Virtual functions class A { float a; virtual void f (float); virtual void g (float); virtual void h (float); }; class B : A {float b; void f (float);}; class C: B {float c; void g (float);}; float a Object Layout for Object of type C float b float c __vptr type_info C::g () C *pg; Pg->g (2.0);  (*(pg->__vptr[0])) (pg, 2.0) B::f () A::h ()

  11. class A { ..}; class B {..}; class C:A, B {}; C is a A & a B The declaration class C:B, A {}; is equivalent to above Assume A has a method af () and B has a method bf () Multiple Inheritance – Simple pf A Part C *pf; pf->bf (); B Part B::bf defined from here C Part delta B f__f1B(B*)((char*pf+delta B)) For ambiguities in this case see section 4.3 of the paper

  12. Casting C* pc; B* pb; pb=(B*)pc; /*pb =(B*)((char*)pc+delta(B)) */ pb=pc; /*pb = (B*)((char*)pc+delta(B))*/ pc=pb; // error: cast needed pc=(C*)pb; /*pc = (C*)((char*)pb-delta(B))*/ Comparisons pc == pb; /* pc ==(C*)pb or equivalently (B*)pc == pb which is,(B*)((char*)pc+delta(B)) == pb or equivalently pc == (C*)((char*)pb-delta(B)) */ Zero Valued pointers C* pc = 0; B* pb = 0; if (pb == 0) ... pb = pc; // pb = (B*)((char*)pc+delta(B)) if (pb == 0) .. So use pb = (pc ==0)?0: (B*)((char*)pc+delta(B)) Interesting Use Cases

  13. class A {virtual void f ()}; class B { virtual void f (); virtual void g (); }; class C:A, B {void f ();}; MI – with Virtual functions A Part struct vtbl_entry { void *(fct) (); int delta;}; B Part C::f () -delta B __vptr B::g () 0 C Part __vptr C::f () 0 B::g () delta B B *pf = new C; pf->f (); // Should call C::f () For ambiguities in this case see section 5.2 of the paper

  14. Multiple Inclusions • A class can have any number of base classes like class C:A, B, D, E, F {..}; • Illegal to specify a class name twice in the list class C:A, B,B, F {..}; //illegal • A may be included more than once as a base class class L {..}; class A:L {..}; class B:L {..}; C:A,B {..}; • For scope resolution and type checking please see sec. 6.2 and 6.3 in paper.

  15. MI with Virtual Base Classes • Independent MI • One Object of the base class in the final derived class, irrespective of the number of times derived. • Base classes can be declared virtual to achieve the above like this class AW: virtual W {...}; class BW: virtual W {...}; class CW:AW,BW{}; • W shared between AW and BW • Except for the unique object, this is just similar to the non-unique case.

  16. Casting allowed from the derived class to the base class but not vice-versa The latter requires a “back-pointer” and unsuitable C++. Use virtual functions instead  Object Model with Virtual Base Class ptr to w ptr to w ptr to aw ptr to cw AW Part AW Part W Part BW Part CW Part W Part

  17. class W { virtual void f(); virtual void g(); virtual void h(); virtual void k(); }; class AW: virtual W {void g();}; class BW: virtual W {void f();}; class CW: AW ,BW {void h();}; CW* pcw = new CW; pcw->f(); // BW::f() pcw->g(); // AW::g() pcw->h(); // CW::h() ((AW*)pcw)->f(); // BW::f(); Virtual Functions ptr to w d (BW) – d (W) BW::f AW Part AW::g -d (W) -d (W) CW::h BW Part 0 W::k CW Part vptr W Part Ambiguities detected at vtbl construction time

  18. Virtual Bases • Method combination, not supported in C++ • Call and return a solution to mimic :before () and :after () • Method combination can be achieved using manually • Problem is to avoid multiple calls to the same function in the virtual class • See 7.3 of the paper for a good example • Constructors and Destructors • Ctor for base classes are called before Ctor for derived classes • Dtors are reverse • Ctors are called as they appear in the list but the virtual base is constructed first.

  19. Controversies • Tom Cargill, 1991, First C++ Conference, Santa Fe • Jim Waldo, 1993 • Smalltalk doesn’t implement MI • BS first implementation had additional overhead. • BS focused on implementation. • Too hard to use, poor design an buggy code • Delegation is an alternative • Makes GC and tools difficult.

  20. Alternative Object Layout for MI class A {virtual void f ()}; class B { virtual void f (); virtual void g (); }; class C:A, B {void f ();}; A Part B Part __vptr B::g C Part __vptr C::f () 0 • Compact virtual function tables • Faster calls to virtual functions if delta is 0 • Delta is 0 for SI • Less portable • ‘goto’ is not supported on m/c architectures this -= delta (B) goto c::f

  21. Presented at EUUG in May 1987 Class specified like this class B {int b; void f();}; class C: *p {B*p; int c;} The :*p meant that something like this void f (C* q) { q->f (); //meaning q->p->f(); } Delegation B *p int c int b • Very promising as delegation could be used to reconfigure object at run-time • Implementation trivial, run-time space efficiency ideal • Bugs and confusion, removed from Release 2.0 • Functions in delegating class do not override • Delegated fn. cannot call delegating fn,

  22. Overheads • One operation with a constant for each use of a member in a base class. • Only with MI • One word per function in each vtbl(to hold the delta). • Normal use case • One memory reference and one operation for each call of a virtual function. • Normal use case • One memory reference and one operation for access of a base class member of a virtual base class. • Only with MI

  23. What makes a language facility hard to use? Lots of rules. Subtle differences between rules. Inability to automatically detect common errors. Lack of generality. Deficiencies. Ambiguities are illegal. Rules for use of members are what they were for single inheritance. Visibility rules are what they were for single inheritance. Initialization rules are what they were for single inheritance. Violations of these rules are detected by the compiler. Easier to implement Portability is not affected Conclusions

More Related