14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, open books for an open world

Embed Size (px)

Citation preview

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    1/48

    Programming Language Concepts Using C and C++/Object

    Orientation and Inheritance in C++

    Logic of inheritance does not change much from one programming language to another. For instance, if base and derived classes

    share the same public interface, the derived class is said to be a subtype of its base class and instances of it can be treated as

    instances of the base class. Or, thanks to dynamic dispatch, inheritance can be used to provide polymorphism.

    However, newcomers to C++ from Java, or any other object-oriented programming language for that matter, are in for a few

    surprises. What we will do in this chapter is to take a look at inheritance in C++ and underline the differences with other

    programming languages.

    Contents

    1 Inheritance Peculiarities in C++

    1.1 Inheritance Kinds

    1.2 No Member Initialization

    1.3 Default Dispatch Type is Static Dispatch1.4 Hide-by-name Overloading

    1.5 Multiple Inheritance, No Root Class

    1.6 Test Program

    2 Inheritance a la Java

    2.1 Root Class and the Interface Concept

    2.2 Module

    2.2.1 Interface (Rational)

    2.2.2 Implementation (Rational)

    2.2.3 Interface (Whole)

    2.2.4 Implementation (Whole)

    2.3 Exception Classes

    2.4 Test Program

    3 Private Inheritance3.1 Interface (List)

    3.2 Implementation (List)

    3.3 Interface (Stack)

    3.4 Implementation (Stack)

    4 Virtual Inheritance

    5 Implementing Polymorphism

    5.1 vtables

    5.2 Adjustor Thunks

    5.3 Complications due to Multiple Inheritance

    6 Constructor and Destructor Call Order

    6.1 An Object with Primitive Type Fields

    6.2 An Object Composed of Sub-object(s)

    6.3 Creating an Array of Objects

    6.4 Inheritance

    6.5 Member Initialization List

    6.6 Multiple Inheritance

    6.7 Restating the Formula: Inheritance is Compiler-Managed Composition

    6.8 Virtual Inheritance

    7 Notes

    Inheritance Peculiarities in C++

    Inheritance Kinds

    First peculiarity of C++ is the assortment of inheritance kinds it offers to programmers: public, protected, and private. This meets

    the newcomer with the first inheritance example she tries. Take a look at the following code snippet.

    cl ass D : B { . . . }

    gramming Language Concepts Using C and C++/Object Orientation a... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    48 20-11-2014 13:08

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    2/48

    This innocent-looking code claims to derive Dfrom B. However, it will not let you treat an object of Das an object of B. Thatsright: Dis not seen as a subtype of B. It looks like either C++ or the programmer got it wrong. Not exactly! Similar to the defaultsection being pri vat e, inheritance, unless otherwise stated, is taken to be of the so-called private kind. Deferring the answer ofwhat we mean byprivate inheritanceto another section, we modify the above code to meet our expectations as given below.

    cl ass D : publ i c B { . . . }

    Done with this peculiarity, lets move on to see some code examples. We will be using the following class definitions throughout

    the examples.

    cl ass B { publ i c: B( voi d) { } voi d f 1s( voi d) { cout

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    3/48

    . . . B* b; i f ( bool _expr ) b = new D( ) ; el se b = new B( ) ; b- >f 1d( ) ; . . .

    A virtual function is dispatched dynamically. So, unlike the previous one, this example will compile and yield an output

    depending on the value of bool _expr . If it evaluates to trueit will output "In D::f1d(void)", otherwise it will output "In

    B::f1d(void)".

    Hide-by-name Overloading

    . . . D* d = new D( ) ; i nt i = 3; d- >f 2( i ) ; / / wi l l be di spat ched t o D: : f 2( shor t ) . . .

    With Java semantics, above code outputs "In B::f2(int)". After all, dis also an object of type Band can use the public interfaceof Bjust like a genuine Bobject. So, both D: : f 2( shor t ) and B: : f 2( i nt ) are exposed to clients of d. Not in C++! Unlike

    Java, where base and derived class member functions make up a set of overloaded functions, C++ restricts this set to a singlescope. Since derived and base classes are different scopes, any derived class function with a name coinciding with a base class

    function will shadow all the functions in the base class. Technically, we say C++ hides by name while Java is said to hide by

    signature.

    But doesnt it go against the logic of inheritance? You claim dto be an object of B(through the public inheritance relationship)and dont let its clients use some function appearing in the public interface of B? Thats right and C++ provides means to meetyour expectations.

    Example: Delegation

    cl ass B { publ i c: . . . voi d f 2d( i nt i ) { cout

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    4/48

    cl ass B { publ i c: . . . voi d f 2u( str i ng s) { cout

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    5/48

    vi r t ual voi d f 2d( i nt i ) { cout

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    6/48

    cout

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    7/48

    voi d no_member_ i ni t i al i zat i on( vo id) {79.

    cout

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    8/48

    In Java, expressing common attributes among unrelated objects is made possible by means of the root class and the interface

    concept. The former defines a common denominator among all classes, while the latter is used to classify a group of classes.[1]

    For instance, because it is listed in Obj ect all objects can be tested for equality with an object of a compatible type; or objectsof classes claiming to be Comparabl ecan be compared with a compatible object.

    These two notions are not supported in C++ as a linguistic abstraction. Instead, programmers are expected to resort to using

    conventions or simulate it through other constructs. For instance, testing for equality is accomplished by overriding the default

    implementation of the ==operator; interface concept, which is not directly supported, can be simulated by means of abstractclasses with pure virtual functions.

    Object

    #i f ndef OBJ ECT_HXX1.

    #def i ne OBJ ECT_HXX2.

    3.

    namespace Syst em {4.

    c l ass Obj ect {5.

    Our intention in having the header file Obj ect is to define a root class that can be used as a polymorphic type in genericfunctions, such as compar eTodefined in I Compar abl e; we do not mean to provide any shared functionality as is done inObj ect class of Java. This, however, cannot be accomplished simply by defining an empty class. In order for a type to bepolymorphic in C++ it must have at least one virtual function. We therefore include a dummy virtual function in our class

    definition.

    But then, why did we make its access modifier pr ot ect ed? First of all, it cannot be publ i cbecause we dont want any

    functionality to be exposed through this class. What about declaring no_op to be pri vat e? After all, declaring it asprotectedmeans deriving classes can now send the no_opmessage. Answer lies in the nature of polymorphism: In order forpolymorphism to be possible, one should be able to override the definition of a dynamically-dispatched function found in the

    base class. This implies such functions should be open at least to the derived classes. As a matter of fact C++ compilers will not

    even let you declare vi rt ual functions in a private section.

    protect ed:6.

    vi r t ual voi d no_op( voi d) { return; }7.

    }; / / end of c l ass Obj ect8.

    } / / end of namespace Syst e9.

    10.

    #endi f11.

    Definition: Apure virtual functionis a virtual function that is not given a function body in the declaring class. A derived class

    claiming to be concrete must therefore provide an implementation for such a function.

    In terms of C++-supported concepts, an interface is a "fieldless" abstract class whose all functions are pure virtual.

    IComparable

    gramming Language Concepts Using C and C++/Object Orientation a... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    48 20-11-2014 13:08

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    9/48

    #i f ndef I COMPARABLE_ HXX1.

    #def i ne I COMPARABLE_HXX2.

    3.

    #i ncl ude "Obj ect"4.

    5.

    namespace Syst e {6.

    c l ass I Comparabl e {7.

    publ i c:8.

    vi r t ual i nt compar eTo( const Obj ect ) const = 0;9.

    }; / / end of cl ass I Comparabl e

    10.

    } / / end of namespace Syst e11.

    12.

    #endi f13.

    Module

    Interface (Rational)

    Rational

    #i f ndef RATI ONAL_HXX1.

    #def i ne RATI ONAL_HXX2.

    3.

    #i ncl ude 4.

    usi ng namespace st d;5.

    6.

    #i ncl ude "I Comparabl e"7.

    #i ncl ude "Obj ect"8.

    usi ng namespace System;9.

    10.

    #i ncl ude "math/ except i ons/ NoI nverse"11.

    #i ncl ude "mat h/ except i ons/ Zer oDenomi nator "12.

    13.

    gramming Language Concepts Using C and C++/Object Orientation a... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    48 20-11-2014 13:08

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    10/48

    #i ncl ude "mat h/ except i ons/ ZeroDi vi sor"

    usi ng namespace CSE224: : Mat h: : Except i ons;14.

    15.

    namespace CSE224 {16.

    namespace Mat h {17.

    Having defined the interface concept as a variation on the class concept, we naturally should be cautious about speaking of the

    implementation relation. This is indeed the case in C++: one can speak of the extension relation only. As a consequence support

    for multiple inheritance is a must.

    c l ass Rat i onal : publ i c Obj ect , publ i c I Compar abl e {18.

    publ i c:19.

    Rat i onal ( l ong nu = 0, l ong den = 1) t h ro ( ZeroDenomi nat or ) {20.

    i f ( den == 0) {21.

    cerr < "Er r or : " ;22.

    cerr < "About t o t hrow Zer oDenomi nator except i on" < endl ;23.

    th ro Zer oDenomi nat or ( ) ;24.

    } / / end of i f ( den == 0)25.

    _n = num;26.

    _d = den;27.

    t hi s- >s i mpl i f y ( ) ;28.

    } / / end of const ruct or ( l ong=, l ong=)29.

    30.

    Rat i onal ( Rati onal & exi st i ngRat ) {31.

    _n = exi s t i ngRat . _n;32.

    _d = exi s t i ngRat . _d;33.

    } / / end of copy const r uct or34.

    Notice the following functions, unlike the rest of the member functions, will be dispatched statically. In Java, such an effect can

    be achieved by declaring methods to be final.

    l ong getNumer at or ( voi d) const { return _n; }36.

    37.

    gramming Language Concepts Using C and C++/Object Orientation a... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 48 20-11-2014 13:08

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    11/48

    l ong getDenomi nat or ( voi d) const { return _d; }

    In addition to marking functions vi r t ual , we also declare them to return a reference. This is because a reference is the best

    candidate for serving the purpose of handles in Java: it is an inheritance-aware, compiler-managed pointer.[2]That is, we can

    pass as argument to the next function [or any function expecting a reference to Rati onal , for that matter] an object belongingin the class hierarchy rooted by the Rat i onal class; dereferencing of a reference is automatically done by the compiler-

    synthesized code.

    As an alternativealthough the resulting code would be less writable and readablewe could have used a plain pointer.

    However, using a plain object type is out of question. This is due to the fact that polymorphism together with inheritance requires

    sending the same messagethat is what polymorphism is all aboutto objects of probably varying sizesenter inheritance

    which in turn implies passing and returning variable-sized objects. This is something compilers cannot deal with! We should

    provide some assistance, which we do by injecting a fixed-size programming entity in between: pointer or reference.

    vi r t ual Rati onal & add( const Rati onal &) const ;39.

    vi r t ual Rati onal & di v i de( const Rati onal &) const t hrow( ZeroDi vi sor)40.

    vi r t ual Rati onal & i nver se( vo i d) const throw( NoI nverse) ;41.

    vi r t ual Rati onal & mul t i pl y( const Rat i onal &) const ;42.

    vi r t ual Rati onal & subt r act ( const Rat i onal &) const ;43.

    vi r t ual i nt compar eTo( const Obj ect &) const ;44.

    Note the following function serves a purpose akin to that of t oSt ri ngin Java. Replacing sstream instead of ostreamandchanging the implementation accordingly would make the analogy a more perfect one.

    f r i end ostr eam& oper ator

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    12/48

    Implementation (Rational)

    Rational.cxx

    #i ncl ude 1.

    #i ncl ude 2.

    usi ng namespace st d;3.

    4.

    #i ncl ude "Obj ect"5.

    usi ng namespace System;6.

    7.

    #i ncl ude "math/ except i ons/ NoI nverse"8.

    #i ncl ude "mat h/ except i ons/ Zer oDenomi nator "9.

    #i ncl ude "mat h/ except i ons/ ZeroDi vi sor"10.

    usi ng namespace CSE224: : Mat h: : Except i ons;11.

    12.

    #i ncl ude "math/ Rati onal "13.

    14.

    namespace CSE224 {

    15.

    namespace Mat h {16.

    Rat i ona l Rat i onal : :17.

    add( const Rat i onal r hs) const {18.

    Note the missing t r y- cat chblock! Unlike Java, C++ does not mandate the programmer to put all potentially problematic codein a guarded region. One can say all C++ exceptions are treated like the Java exceptions deriving from the

    Runti meExcept i onclass. This gives the programmer a degree of freedom that enables her to come up with cleaner code. Forinstance, reaching the next line means we are adding two well-formed Rat i onal objects. Result of such an action can nevercreate a problem!

    Rat i onal * sum = new Rati onal (_n * rhs . _d + _d * r hs . _n, _d * r hs . _ d) ;19.

    20.

    return sum- >s i mpl i f y( ) ;21.

    } / / end of Rat i onal & Rati onal : : add(const Rati onal &) const22.

    23.

    24.

    gramming Language Concepts Using C and C++/Object Orientation a... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 48 20-11-2014 13:08

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    13/48

    Rat i ona l Rat i onal : :

    di vi de( const Rat i onal r hs) const t hrow( ZeroDi vi sor ) {25.

    t r y {26.

    Rat i ona l tmp_ i nv = r hs. i nver se( ) ;27.

    Rat i onal r et _ r at = t hi s - >mul t i pl y( t mp_i nv) ;28.

    Now that we are done with the temporary object that holds the inverse of r hs , we must return it to the memory allocator or putup with the consequences of creating garbage at each use of this function. Thats pretty annoying! But then again, a C/C++

    programmer does not make such easy mistakes.

    Notice the address-of operator before t mp_i nv. Application of this operator to a reference returns the starting address of theregion aliased by the reference. [Remember references are silently dereferenced at their point of use] In our case, this will be the

    address of the object created as a result of sending the message i nver seto r hs.

    del et e &t mp_i nv;28.

    return ret_ rat ;29.

    } catch ( NoI nver se e) {30.

    cerr

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    14/48

    Rat i onal * res = new Rati onal (_n * r hs . _n, _d * r hs . _ d) ;49.

    50.

    return r es - >s i mpl i f y( ) ;51.

    } / / end of Rat i onal & Rat i onal : : mul t i pl y(const Rat i onal &) const52.

    53.

    Rati onal & Rati onal : :54.

    subt r act( const Rati onal & r hs) const {55.

    We formulate subtraction in terms of other operations: instead of subtracting a value, we add the negated value. For doing this

    we create two temporary objects meaningful only throughout the current call. Before returning to the caller we should return

    them to the memory allocator.

    A so-called smart pointer object is exactly what we want. Such an object is initialized to point to a dynamically allocated object

    created by a new expression and frees itthe dynamically allocated objectat the end of its (smart pointers) lifetime. The

    following figure showing the memory layout after execution of line 47 should make this clear.

    Heap object local to the function is created together with the smart pointer object, which is itself a local object created on the

    run-time stack.9 This means allocation-constructor call and destructor call-deallocation of this smart pointer object will be

    handled by the compiler-synthesized code. In other words, programmer need not worry about the life-cycle management of the

    smart pointer object. So, if we can guarantee the heap object is destroyed-deallocated together with this smart pointer, its

    life-cycle management will not be a problem anymore. This is accomplished by delet(e)ing the heap object within the destructor

    of the related smart pointer object, which means the heap object will have been destroyed-deallocated by the time the

    destruction of the smart pointer object is over. The following then describes the life-cycle of the smart pointer and the related

    heap object.

    Create the smart pointer in the run-time stack.

    Pass the related heap object to the constructor of the smart pointer.1.

    1.

    Use the heap object.2.

    Call the destructor of the smart pointer by means of the compiler-synthesized code.

    Delete the heap object from within the destructor of the smart pointer.1.

    3.

    According to this, anonymous Rat i onal objectsnew Rat i onal ( - 1) and &( rhs. mul t i pl y( *neg_1) )created inthe following definitions will have been automaticallythat is, without the intervention of the programmerreturned before

    leaving the function.

    auto_pt r neg_1( new Rati onal ( - 1) ) ;56.

    aut o_pt r t mp_ mul ( &( rhs. mul t i pl y( *neg_1) ) ) ;57.

    gramming Language Concepts Using C and C++/Object Orientation a... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 48 20-11-2014 13:08

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    15/48

    Observe the following application of the dereferencing operator receives as its operand a non-pointer variable, which may at first

    seem as an error. After all, * works by returning the contents of memory indicated by its sole operand. However, this ratherlimited description ignores the possibility of overloading the dereferencing operator. It is indeed the overloaded version of this

    operator that enables the use of a non-pointer type. The following application of * makes use of the overloaded version definedwithin the aut o_pt r class, which returns the contents of the heap object managed by the smart pointer.

    To make things clearer, we can suggest the following implementation for the aut o_pt r class.

    t empl ate cl ass aut o_pt r { publ i c: aut o_pt r ( ManagedObj ect Type* managedObj ) { _managed_heap_obj ect = managedObj ; . . . } / / end of const ructor( ManagedObj ectType*)

    . . .

    ManagedObj ect Type oper ator*( voi d) { . . . return *_managed_heap_obj ect ; } / / end of ManagedObj ect Type oper ator*( voi d)

    . . . pri vat e: ManagedObj ect Type* _managed_heap_obj ect ; } / / end of cl ass aut o_pt r

    Rat i onal &re t _ ra t = add( *t mp_ mul ) ;58.

    59.

    return( ret_ rat ) ;60.

    } / / end of Rat i onal & Rat i onal : : subtr act (const Rat i onal &) const61.

    62.

    i nt Rati onal : :63.

    compar eTo( const Obj ect & r hs) const {64.

    doubl e t hi s _equi = ( ( doubl e) _n) / _d;65.

    In addition to the traditional C-style casting C++ offers a variety of cast operators: const_cast , dynami c_cast ,st at i c_cast , and rei nt er pr et _cast . Each of these performs a subset of the functionality offered by the traditional castoperator and therefore one can say the new operators do not add any new functionality. Nevertheless, thanks to the extra support

    from the compiler, they enable writing more type-safe programs. Using the new operators we state our intentions explicitly and

    therefore get more maintainable code.

    Example: Removing const-ness property of an object.

    cl ass B { }; . . .

    gramming Language Concepts Using C and C++/Object Orientation a... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 48 20-11-2014 13:08

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    16/48

    const B cb = B; . . . B b = const _cast ( cb) ; / / equi val ent t o ( B) cb or B ( cb) . . . .

    It should be noted that const_cast can also be used to change vol at i l e-ness property of an object.

    Since our intention of removing the const -ness has been made explicit by the relevant operator, maintainer of the code willmore quickly spot the occurrence of cast and realize what is being done. Alternative scheme of using the C-style cast lacks these

    qualities: it is both difficult to find the location of the cast and figure out that const -ness is being removed.

    Using dynami c_cast will also provide us with the benefit of safer code. This particular operator is used to bi-directionally castbetween polymorphic classesthat is; classes that has at least one virtual functionthat are related with each other by a public

    derivation.

    Question

    dynami c_cast can be used to convert only between pointer/reference types. Why?

    Answer

    Polymorphic classes enable behavioral and structural variability. This can only be utilized by means of a pointer/reference,

    which acts as a facade between the static world required by the compiler/linker and the variability demanded by a dynamic

    world. Therefore, dynami c_cast , used to cast between polymorphic classes, expects its parameter to be apointer/reference and returns a pointer/reference.

    Definition: Converting from one class to another in the same class hierarchy is referred to as downcastingif the target type is

    more specialized. In case the target type is less specialized the act of casting is called upcasting.

    Upcasting to a public base class is always successful since the messages listed in the interface of the target type is a subset of the

    source type interface. On the other hand, casting from a derived class to one of its non-public base classes leads to a

    compile-time error. Similarly, downcasting may give rise to run-time errors since we can potentially send messages that are not

    found in the interface of the source type.

    Example: Safer code with dynamic_cast.

    cl ass PB { vi r t ual voi d f( voi d) { } }; cl ass PD : publ i c PB { vi r t ual voi d g( voi d) { } }; . . . PB* pb; . . . ; pb = new D; . . . PD* pd = dynami c_cast ( pb) ; i f ( pd == NULL) { . . . } . . .

    The above code downcasts a PB*variable to PD* , through which one can send the extra message named g. For this example,

    this doesn't seem to be a problem. But what if pbwas used to point to an object of PBinstead of PD? What if it is used to pointto objects of different types as is shown in the following fragment?

    i f( some_condi t i on) { . . . ; pb = new D; . . . } el se { . . . ; pb = new B; . . . } . . . PD* pd = dynami c_cast ( pb) ;

    There is no guarantee that we can send gto the underlying object, which can be of type PBor PD. This guarantee we are seekingcan be provided only if we can check the object type at run-time. And this is exactly what dynami c_cast does: by checkingcompatibility of the pointer/referencestatic typewith the objectdynamic typedynami c_cast decides whether the casttaking place is valid or not. If so a legitimate value is returned. Otherwise, in the case of casting a pointer, a NULLvalue isreturned, which basically removes any possibility of sending an illegal message; in the case of failing to cast a reference

    st d: : bad_cast exception is thrown. Same actions are taken also when source and target types are not related withinheritance.

    Note this cost due to the run-time check performed by the compiler-synthesized code is never experienced as a result of using

    the traditional cast operator. This is because the C-style cast operator makes no use of any run-time information.

    gramming Language Concepts Using C and C++/Object Orientation a... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 48 20-11-2014 13:08

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    17/48

    Observe casting up the class hierarchysince messages received by an object of the derived class is a subset of that of its base

    classesdoes not need any run-time checks. This means cost due to dynami c_cast is not rationalized: why should we pay formaking a control, whose result is known to us? Solution offered by C++ is another cast operator that does its job using

    compile-time information: stati c_cast . This operator can be used for performing conversions that are implicitly carried outby the compiler, performing these implicit conversions in the reverse direction. It can also be used in place of dynami c_cast ifskipping the run-time checks is guaranteed to be safe.

    Example:

    PD* ppd = new PD; / / I mpl i ci t conver si on, equi val ent t o st at i c_cast ( ppd) PB* ppb = ppd; . . . PD pd = PD; / / I mpl i ci t conver si on, equi val ent t o st at i c_cast ( pd) PB pb = pd; . . . enum I t er at or _Type {I TERATOR_FORWARD, I TERATOR_BACKWARD}; i nt one = I TERATOR_BACKWARD; / / I mpl i ci t conver si on i nt val ; . . .

    / / rever se conversi on I t er at or _Type i t r_ t ype = st at i c_cast( val ) ;

    PB* pb = new PB( ) ; / / Nor mal l y, next l i ne shoul d have been wr i t t en wi t h dynami c_cast . But i f we can makesure pd does not get a g message i t i s OK and wi l l save us t he r un- t i me checksper f or med by dynami c_cast . PD* pd = stati c_cast( pb) ; / / pd i s i ni t i al i zed wi t h a l egi t i mat e poi nt er

    This doesn't fully cover the functionality offered by the traditional cast operator. Conversions between unrelated/incompatible

    pointer types are missing, for instance. This missing functionality is covered by the rei nt er pr et _cast operator , which

    can also perform conversions between pointer and integral types.

    Example:

    f l oat f = 1. 0; f l oat * f p = &f; i nt* i p = r ei nt erpret _cast ( f p) ;

    cout

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    18/48

    l ong Rati onal : :72.

    mi n( l ong n1, l ong n2) { return ( n1 > n2 ? n1 : n2) ; }73.

    74.

    Rati onal & Rati onal : :75.

    s i mpl i f y( vo id) {76.

    l ong upperLi mi t = mi n(_n, _d) ;77.

    78.

    f or ( l ong i = 2; i

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    19/48

    6.

    #i ncl ude "math/ Rat i onal "7.

    8.

    namespace CSE224 {9.

    namespace Mat h {

    10.

    c l ass Whol e : publ i c Rat i onal {11.

    publ i c:12.

    Remember Whol ederives from Rat i onal . Put differentlysince inheritance can be seen as a compiler-managedcompositionall Whol eobjects have a Rati onal sub-object as part of their memory layouts. Following notation used in themember initialization list with no reference to the member being initialized will initialize the Rat i onal sub-object found in theWhol eobject being constructed.

    Whol e( l ong num) : Rati onal ( num) { }13.

    Whol e( voi d) : Rat i onal ( 0) { }14.

    Whol e( Whol e& exi st i ngWhol e) : 15.

    Rati onal ( exi st i ngWhol e. get Numer at or ( ) ) { }16.

    Whol e& add( const Whol e& r hs) const ;

    17.

    vi r t ual Rati onal & add( const Rat i onal &) const ;18.

    }; / / end of cl ass Whol e19.

    } / / end of namespace Mat h20.

    } / / end of namespace CSE22421.

    22.

    #endi f23.

    Implementation (Whole)

    Whole.cxx

    #i ncl ude 1.

    us i ng names pace st d;2.

    3.

    #i ncl ude "math/ Rat i onal "4.

    gramming Language Concepts Using C and C++/Object Orientation a... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 48 20-11-2014 13:08

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    20/48

    #i ncl ude " mat h/ Whol e"

    5.

    6.

    namespace CSE224 {7.

    namespace Mat h {8.

    Rati onal & Whol e: :

    9.

    add( const Rati onal & r hs) const {10.

    cout

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    21/48

    namespace Mat h{

    namespace Except i ons {9.

    c l ass NoI nvers e {

    10.

    publ i c:11.

    NoI nverse( l ong num, l ong den) {12.

    cer r

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    22/48

    cer r

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    23/48

    Test Program

    Test_Whole.cxx

    #i ncl ude 1.

    #i ncl ude

    2.

    us i ng names pace st d;3.

    4.

    #i ncl ude " mat h/ Whol e"5.

    usi ng names pace CSE224: : Mat h;6.

    7.

    #i ncl ude " mat h/ except i ons/ Zer oDenomi nator "8.

    us i ng names pace CSE224: : Mat h: : Except i ons;9.

    10.

    i nt mai n( voi d) {11.

    cout

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    24/48

    cout

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    25/48

    cout

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    26/48

    ~Li st ( voi d) ;

    Li s t oper at o r=( const L i s t ) ;15.

    bool operat or==( const L i s t ) ;16.

    17.

    doubl e get _ f i r s t ( vo id) t hr ow( Li st _Empty) ;18.

    doubl e get_ l ast ( voi d) t h ro ( Li st _Empty) ;19.

    vo id i nsert _at_end( doubl e new_i t e ) ;

    20.

    vo id inser t _ i n_ f r ont ( doubl e new_i t e ) ;21.

    doubl e remove_ f r om_end( voi d) t h ro ( Li st _Empty) ;22.

    doubl e r emove_f r om_f r ont ( voi d) throw( Li st _Empty) ;23.

    bool i s_empt y( voi d) ;24.

    unsi gned i nt s i z e( voi d) ;

    25.

    26.

    pr i vat e:27.

    What follows is the definition of a nested class, a class defined inside another. Such a class, when defined in a pri vat esection, is not visible outside its enclosing class. This scheme is useful when the two classes are tightly coupled, as is the case in

    our example: A Li st _Nodeobject is used only in the context of a Li st object. What makes up our Li st objects is animplementation detail and should not be a concern to their users.

    Although it might be tempting to draw a parallel between nested classes and inner classes of Java, that would be a mistake. As

    opposed to the special relation between the inner class and its enclosing class, in C++ the enclosing class has no special access

    privileges with regard to the classes nested within it. For this reason, changing publ i cto pri vat eor pr ot ect edis not agood idea.

    Another remark to be made is that nested classes of C++ do not keep any record of the enclosing object in the objects of the

    inner class, which makes them like more the static inner classes of Java.

    c l ass Li st _Node {

    28.

    publ i c:29.

    Li st _Node( doubl e val ) : _ i nf o( val ) , _next ( NULL) , _prev( NULL) { }30.

    31.

    doubl e _ i n f o;32.

    Li st _Node *_next , *_pr ev;33.

    }; / / end of c l ass Li s t_Node34.

    pr i vat e:35.

    Li st _Node *_head, *_t ai l ;36.

    37.

    gramming Language Concepts Using C and C++/Object Orientation a... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 48 20-11-2014 13:08

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    27/48

    unsi gned i nt _ si z e;

    A function declared in the pr i vat esection? Yes! Functions, which are used by other functions and are not part of theinterface, are declared in the pr i vat esection. Note that you cannot get away without declaring such functions in the classinterface.

    vo id i nser t _ f i r s t _node( doubl e) ;38.

    }; / / end o f L i s t c l ass39.

    } / / end of namespace DS40.

    } / / end of namespace CSE22441.

    42.

    #endi f43.

    Implementation (List)

    List.cxx

    #i ncl ude

    1.

    us i ng names pace st d;2.

    3.

    #i ncl ude "ds/ Li st"4.

    #i ncl ude "ds/ except i ons/ Li st _Except i ons"5.

    usi ng names pace CSE224: : DS: : Except i ons;6.

    7.

    namespace CSE224 {8.

    namespace DS {9.

    Li s t : :10.

    L i s t ( const Li s t& r hs) : _head( NULL) , _ t ai l ( NULL) , _ s i z e( 0) {11.

    Li st _Node *p t r = r hs. _head;12.

    f or ( unsi gned i nt i = 0; i < rhs. _ si z e; i ++) {13.

    t hi s- >i nsert _at _end( pt r - >_ i nf o) ;

    14.

    p t r = pt r - >_next ;15.

    } / / end of f or (uns i gned i nt i = 0; i < rhs. _s i ze; i ++)16.

    gramming Language Concepts Using C and C++/Object Orientation a... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 48 20-11-2014 13:08

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    28/48

    } / / end of copy const r uct or17.

    Now that nodes of the Li st objects are allocated on the heap, we must make sure they are turned back over to the memoryallocator as the Li st object itself is, implicitly or explicitly, deleted. For this reason, we need to write a destructor to free thesenodes. Note a Li st object is made up of two pointers, which show the head and the tail of the list, and a field holding its size.The nodes pointed, directly or indirectly, by these pointers are not part of the

    Li stobject. So, they will not be automatically

    freed together with the list object. For this reason, we do need a destructor.

    Notice our decision is not affected by whether the Li st object itself is created on the heap or not. Where the Li st object iscreated has an effect on who should call the destructor: Whoever the responsible party might be, compiler or programmer, in all

    possible scenarios the destructor is implicitly called before deallocation of the object. If it is created on the heap the programmer

    is responsible for making the call. Otherwise, the compiler will take care of the drudgery as the scope of the object is closed.

    Li s t : :19.

    ~Li st ( voi d) {20.

    f or ( i nt i = 0; i 0; i - - )29.

    t hi s- >r emove_f r om_f r ont ( ) ;30.

    Li st _Node *p t r = r hs. _head;31.

    f or ( unsi gned i nt i = 0; i < rhs. _ si z e; i ++) {32.

    t hi s- >i nsert _at _end( pt r - >_ i nf o) ;33.

    pt r = pt r - >_next ;34.

    } / / end of f or (uns i gned i nt i = 0; i < rhs. _s i ze; i ++)35.

    36.

    i f ( rhs ._ s i ze == 0) {37.

    _head = _ t ai l = NULL;38.

    _s i ze = 0;

    39.

    } / / end of i f ( r hs . _ s i ze == 0)40.

    41.

    gramming Language Concepts Using C and C++/Object Orientation a... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 48 20-11-2014 13:08

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    29/48

    return ( * t hi s) ;42.

    } / / end of assi gnment operat or43.

    44.

    bool L i s t : :45.

    operat or==( const L i s t & r hs ) {46.

    i f (_si ze ! = rhs . _ s i z e) return f a l s e;47.

    i f (_si ze == 0 | | t hi s == &r hs) return t r ue;48.

    49.

    Li st _Node *p t r = _head;50.

    Li st _Node *ptr_rhs = rhs. _head;51.

    f or ( unsi gned i nt i = 0; i _ i nf o == pt r_ rhs- >_i nf o) )53.

    return f a l s e;54.

    p t r = pt r - >_next ;55.

    ptr_rhs = pt r_ r hs- >_next ;56.

    } / / end of f or (uns i gned i nt i = 0; i < _s i ze; i ++)57.

    58.

    return t rue;

    59.

    } / / end of equal i t y-t est oper at or60.

    61.

    doubl e L i s t : :62.

    get _ f i r s t ( voi d) t h ro ( Li st _Empty) {

    63.

    i f ( i s_empty ( ) ) throw Li st _Empty( ) ;64.

    65.

    return (_head- >_ i nf o) ;66.

    } / / end of doubl e L i s t : : get _ f i r s t ( vo id)67.

    68.

    doubl e L i s t : :69.

    get_ l ast( vo id) t hrow( Li st _Empt y) {70.

    i f ( i s_empty ( ) ) throw Li st _Empty( ) ;71.

    72.

    return (_ t ai l - >_ i nf o) ; 73.

    } / / end of doubl e Li s t : : get _ l as t ( voi d)74.

    gramming Language Concepts Using C and C++/Object Orientation a... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 48 20-11-2014 13:08

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    30/48

    75.

    voi d L i s t : :76.

    i nsert _at _end( doubl e new_i t e ) {77.

    i f ( i s_empty ( ) ) i nser t _ f i r s t _node( new_i t e ) ;

    78.

    el s e {

    79.

    Li st _Node *new_node = new Li st _Node( new_i t em) ;80.

    _ t ai l - >_next = new_node;81.

    new_node- >_pr ev = _ t ai l ;82.

    _ t ai l = new_node;83.

    }84.

    _s i ze++;85.

    } / / end of voi d L i s t : : i nser t _at_end( doubl e)86.

    87.

    voi d L i s t : :88.

    i nser t _ i n_ f r ont ( doubl e new_i t em) {89.

    i f ( i s_empty ( ) ) i nser t _ f i r s t _node( new_i t em) ;90.

    el s e {91.

    Li st _Node *new_node = new Li st _Node( new_i t em) ;92.

    new_node- >_next = _head;93.

    _head- >_pr ev = new_node;94.

    _head = new_node;95.

    }96.

    _s i ze++;97.

    } / / end of vo i d L i s t : : i nser t _ i n_ f ront ( doubl e)

    98.

    99.

    doubl e L i s t : :100.

    r emove_ f r om_end( voi d) t hr ow( Li st _Empty) {101.

    i f ( i s_empty ( ) ) throw Li st _Empty( ) ;102.

    103.

    doubl e ret_val = _ t ai l - >_i nf o;104.

    Li st _Node *t emp_node =_ t ai l ;105.

    106.

    107.

    gramming Language Concepts Using C and C++/Object Orientation a... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 48 20-11-2014 13:08

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    31/48

    i f (_si ze == 1) { head _t ai l = NULL; }

    el s e {108.

    _ t ai l = _ t ai l - _pr ev;109.

    _ t ai l - >_next = NULL;110.

    }111.

    112.

    del ete t emp_node;

    113.

    _s i ze- - ;114.

    115.

    return ret_val ;116.

    } / / end of doubl e Li st : : r emove_f rom_f r ont ( voi d)117.

    118.

    doubl e L i s t : :119.

    r emove_f r om_f r ont ( voi d) t h ro ( Li st _Empty) {120.

    i f ( i s_empty ( ) ) throw Li st _Empty( ) ;121.

    122.

    doubl e ret_val = _head- _i nf o;123.

    Li st _Node *t emp_node =_head;124.

    125.

    i f (_si ze == 1) { _head =_t ai l = NULL; }126.

    el s e {127.

    _head = _head- >_next ;128.

    _head- >_pr ev = NULL;129.

    }130.

    131.

    del ete t emp_node;132.

    _s i ze- - ;133.

    134.

    return ret_val ;135.

    } / / end of doubl e Li st : : r emove_f rom_f r ont ( voi d)136.

    137.

    bool L i s t : :138.

    i s_empt y( vo id) { return(_s i ze == 0) ; }139.

    gramming Language Concepts Using C and C++/Object Orientation a... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 48 20-11-2014 13:08

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    32/48

    140.

    unsi gned i nt L i s t : :141.

    s i z e( voi d) { return _ si z e; }142.

    143.

    voi d L i s t : :144.

    i nser t _ f i r s t_node( doubl e new_i t em) {145.

    Li st _Node *new_node = new Li st _Node( new_i t em) ;146.

    _head = _ t ai l = new_node;147.

    } / / end of voi d L i s t : : i nser t _ f i r s t _node(doubl e)148.

    149.

    ost r eam& operat or

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    33/48

    #i ncl ude 4.

    us i ng names pace st d;

    5.

    6.

    #i ncl ude "ds/ except i ons/ Stack_Except i ons"7.

    us i ng names pace CSE224: : DS: : Except i ons;

    8.

    9.

    #i ncl ude "ds/ Li st"10.

    11.

    namespace CSE224 {12.

    namespace DS {13.

    The Li st class offers a superset of the functionality expected from a stack. This may at first lead us to think that we maydefine a new class, St ack, and have it (publicly) derive from the Li st class. The problem with this approach is that the publicinterface of the base class will be exposed as part of the public interface of the derived class. Not really what we would want in

    this case: the Li st class offers a lot more than what we would expect from the St ackclass. For this reason we should resortto some other method, such as composition.

    C++ offers an alternative:private inheritance. Using private inheritance, the derived class can still make use of the

    functionality offered by the base class but the base class interface is not exposed through the derived class. For this reason,

    St ackclass privately inherits from the Li st class.

    c l ass Stack : pr i vate L i s t {14.

    publ i c:15.

    Now that the derived class can reuse the base class functionality but do not expose it to its users, this type of inheritance is also

    called implementation inheritance. For a similar reason,public inheritanceis also called interface inheritance.

    We do not need to write the functions of the orthodox canonical form because compiler-synthesized versions provide the

    equivalent of what we are required to do. This is basically because the only data field of St ackis the Li st sub-object itinherits from Li st .

    / / Stack( vo i d) ;16.

    / / Stack( const Stack&) ;17.

    / / ~Stack(voi d) ;18.

    / / Stack& oper ator =( const Stack&) ;19.

    / / bool oper ator ==( const Stack&) ;20.

    21.

    gramming Language Concepts Using C and C++/Object Orientation a... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 48 20-11-2014 13:08

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    34/48

    doubl e peek( vo id) t hr ow( St ack_Empt y) ;22.

    doubl e pop( voi d) thro ( St ack_Empt y) ;23.

    vo id push( doubl e new_i t e ) ;24.

    Thanks to the following statement, we selectively expose a function from the privately inherited base class. Its as if the

    i s_empt yfunction(s) from the Li st class were publicly inherited.

    us i ng L i s t : : i s_empt y;26.

    }; / / end of Stack c l ass27.

    } / / end of namespace DS28.

    } / / end of namespace CSE22429.

    30.

    #endi f31.

    Implementation (Stack)

    Stack.cxx

    #i ncl ude 1.

    us i ng names pace st d;2.

    3.

    #i ncl ude " ds/ St ack"4.

    #i ncl ude "ds/ except i ons/ Stack_Except i ons"

    5.

    usi ng names pace CSE224: : DS: : Except i ons;6.

    7.

    namespace CSE224 {8.

    namespace DS {9.

    doubl e St ack: :10.

    peek( voi d) throw( St ack_Empt y) {11.

    doubl e ret_val ;12.

    gramming Language Concepts Using C and C++/Object Orientation a... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 48 20-11-2014 13:08

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    35/48

    Users of our class should not be aware of how we implement the St ackclass. Thats why we need to re-throw the exceptionsthrown by the Li st class so that it makes more sense to the user.

    t r y { ret_val = get _ f i r s t ( ) ; }14.

    catch( Li st _Empty) { t hr ow St ack_Empt y( ) ; }15.

    16.

    return ret_val ;17.

    } / / end of doubl e St ack: : peek(voi d)18.

    19.

    voi d Stack: :20.

    push( doubl e new_i t em) { L i s t : : i nser t _ i n_ f r ont ( new_i t em) ; }21.

    22.

    doubl e St ack: :23.

    pop( vo i d) t hrow( St ack_Empt y) {24.

    doubl e ret_val ;25.

    26.

    t r y { ret_val = r emove_f r om_f r ont ( ) ; }27.

    catch( Li st _Empty) { t hr ow St ack_Empt y( ) ; }

    28.

    29.

    return ret_val ;30.

    } / / end of doubl e St ack: : pop( voi d)31.

    } / / end of namespace DS32.

    } / / end of namespace CSE22433.

    Virtual Inheritance

    With the possibility of multiple inheritance rises the issue of the so-called virtual inheritance. Consider the class hierarchy

    shown in Figure 2. Question that awaits your answer is: How many Ani mal sub-objects will there be in a Pol i t i ci anobject? Looking at the figure the correct answer seems to be two. However, our logic tells us a different story: there can be only

    one Ani mal sub-object in a Pol i t i ci an.

    gramming Language Concepts Using C and C++/Object Orientation a... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 48 20-11-2014 13:08

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    36/48

    Whichever one is the right answer, there might be cases where either one turns out to be a better choice. We must find a way to

    tell the difference between the options. This is where the notion of virtual inheritance comes into the picture. We define the

    Humanoi dand Apeclasses to be virtually derived from Ani mal .

    Example: Virtual inheritance

    cl ass Ani mal { . . . };

    cl ass Humanoi d : publ i c vi rt ual Ani mal { . . . };

    cl ass Ape : publ i c vi rt ual Ani mal { . . . };

    cl ass Pol i t i ci an : publ i c Humanoi d, publ i c Ape { . . . };

    Thanks to these definitions, there is now only one Ani mal sub-object in a Pol i t i ci an. This is achieved by assuring thatpointersnot objects themselvesare inserted into the derived classes. That is; instead of containing two Ani mal sub-objects,a Pol i t i ci anobject now has two pointers both pointing to the same Ani mal sub-object.

    Note use of virtual inheritance causes the order of constructor call to be changed: Virtual base classes are always constructedprior to non-virtual base classes regardless of where they appear in the inheritance hierarchy.

    A typical use of virtual inheritance involves implementation of mix-in classes. Mix-in classes are used for tuning the behavior of

    a base class and can be combined to obtain even more specialized classes. For example, using the following code one can create

    windows with different styles: plain window, window with menu, window with border, and window with menu and border. As a

    matter of fact, we can come up with our own mix-in, say scroll-bar mix-in, and get scroll-bar-supporting versions of these

    window styles.

    Example: Implementing mix-ins by virtual inheritance.

    cl ass Pl ai n_Wi ndow { publ i c: /* Basic window functions common to all windows */ pri vat e: . . . }; / / end of cl ass Pl ai n_Wi ndow

    cl ass Menu_Mi xi n : publ i c vi r t ual Pl ai n_Wi ndow { publ i c: /* Functions specially required for manipulating window menus. */ pri vat e: . . . }; / / end of cl ass Menu_Mi xi n

    cl ass Border _Mi xi n : publ i c vi r t ual Pl ai n_Wi ndow { publ i c: /* Functions specially required for manipulating window borders. */ pri vat e: . . .

    gramming Language Concepts Using C and C++/Object Orientation a... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 48 20-11-2014 13:08

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    37/48

    }; / / end of cl ass Bor der _Mi xi n

    cl ass Wi ndow_wi t h_Menu_and_Border : publ i c Menu_Mi xi n, publ i c Border_Mi xi n { publ i c: . . . pri vat e: . . . }; / / end of cl ass Wi ndow_wi t h_Menu_and_Border

    Note the number of window styles grows exponentially with the number of mix-ins. But, thanks to virtual inheritance, we do

    not have to consider each and every combination. We start out with the base class and a few mix-ins. As we need more refined

    window styles we come up with a new class inheriting from the relevant mix-in classes. If we see certain attributes are missing

    from the mix-in classes we can write our own mix-in and use it like the others.

    Implementing Polymorphism

    In this section, we take a look at two widely used methods of implementing polymorphism. It is worth noting that both rely on

    dynamically dispatching the function call to the relevant [function] entry point. In other words, polymorphism is implemented

    by means of dynamic dispatch. Another point to make is the tool we use for expressing polymorphism: inheritance.

    Mentioning polymorphism, inheritance, and dynamic dispatch in different contexts may make some think of them as unrelatedconcepts. This, however, is utterly wrong. Truth of the matter is, in an object-oriented context these are complementary

    concepts and cooperate for enabling the implementation of the is-a relation in a natural way. In order to express an is-a relation

    between two classes we need help from both inheritance and polymorphism: inheritance is used to define a common message

    protocol between the base and derived classes, whereas polymorphism is needed for providing the behavioral variability.[4]

    This is further made possible by dynamically dispatching the messages.

    As was mentioned in previous section, inheritance without polymorphism leads to inflexible, object-based solutions. Likewise,

    polymorphism alone is generally not what you want. So, it is well-advised that you consider using these two together.

    Previous remarks should not make you think we are bound to use the duo of inheritance and polymorphism only. Our success

    in software industry depends on producing reliable, easily-extensible, efficient software. The keyword in reaching this goal is

    reuse and aforementioned concepts are not without alternatives. Apart from the age-old composition technique, we can use

    generics for instance. Parameterizing a class or a subprogram will also give us the benefits of reuse. An example to the formeris given in the Parameterized Types chapter, while use of the latter is provided below. Thanks to this method, users can sort any

    array provided that a Compar at or object for the component type is also supplied.

    Example: Generic methods in Java.

    publ i c cl ass Bubbl eSort { publ i c s tat i c voi d sort ( V[ ] ar r , Comparator

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    38/48

    implementing polymorphism. But before we do that, we will give a listing of the sample classes used in our presentation.

    cl ass B1 { . . . publ i c: vi r t ual voi d f( i nt ) ; voi d f s( i nt ) ; . . . . . . } ; / / end of base cl ass B1

    cl ass B2 { . . . publ i c: vi r t ual voi d f( i nt ) ; vi r t ual voi d g( voi d) ; . . . . . . } ; / / end of base cl ass B2

    cl ass D : publ i c B1, publ i c B2 {

    . . . publ i c: voi d f( i nt ) ; . . . . . . }; / / end of der i ved cl ass D

    vtables

    The vtable technique, generally used in compilers of the PC world, utilizes a table containing rows of function entry address

    and offset pair. Objects of all classes with at least one dynamically dispatched function has a pointer, called the vptr, pointing

    to the start of this table. The offset column is used for adjusting the value of the thi spointer. This adjustment is required

    when an object of a derived class is used through a pointer of a base class. Take the definition of D, whose object memorylayout is given below. Given an object of D, we can use it through pointers of Dand any type that is an ancestor type of D,which in our case are D*, B1* , and B2* . Put another way, through a variable of type B1*we can manipulate any object that isan instance of a class deriving from B1, which in our case are Dand B1. Accordingly, the following is possible.

    . . . D* d_obj = new D( . . . ) ; B1* b1_obj = new B1( . . . ) ; B2* b2_obj = new B2( . . . ) ;

    . . . f d( D* d_par ) { . . .

    d_par - >f( . . . ) ; d_par - >g( . . . ) ; . . . } / / end of . . . f d( D*)

    . . . f b1( B1* b1_par ) { . . . b1_par - >f( . . . ) ; . . . . . . } / / end of . . . f b1( B1*)

    . . . f b2( B2* b2_par ) { . . . b2_par - >f( . . . ) ; b2_par - >g( . . . ) ; . . .

    gramming Language Concepts Using C and C++/Object Orientation a... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 48 20-11-2014 13:08

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    39/48

    } / / end of . . . f b2( B2*)

    . . . f d( d_obj ) . . . ; . . . f b1( b1_obj ) . . . ; . . . f b1( d_obj ) . . . ; . . . f b2( b2_obj ) . . . ; . . . f b2( d_obj ) . . . ;

    Having overridden fin the derived class (D) means invoking this version of fwill potentially make use of all properties foundin B1, B2, and D, which implies the receiver object of this function must at least be a Dobject. As was mentioned before suchan object can also be manipulated through B2* . This is exemplified by executing line 7 of the above fragment following thecall on line 15. Note also, upon executing the function call on line 14, the function call on line 7 is dispatched with a B2object.Since b2_par is of type B2* , both cases are handled via the vptr field of a B2object. However, in one case this object is B2part of a Dobject whereas in the other it is a plain B2object. This is shown in figures above.

    B2as part of a Dobject needs our attention. Starting address of the object (D) and the pointer used for manipulating this object(B2*) indicate different locations in memory. This requires thatin order to enable use of all properties of a Dobjectweadjust the pointer value as many bytes as there are before the B2sub-object, which is referred to as delta(B2) in our figure.

    Adjustor Thunks

    The second technique we will look at can be seen as a less portable [7]optimization on the first one. As in the vptr technique,one column in the vtable contains a pointer-to-function. But we now utilize thunks instead of the adjustment column. In case

    an adjustment to this is needed, pointer-to-function in the one and only column of the vtable points to the thunk code generated

    by the compiler, which modifies this and jumps to the function entry. If no adjustment to this is required, the pointer-

    to-function contains the address of the entry of the function to be invoked.

    Insert Adjustor Thunks figure here

    Complications due to Multiple Inheritance

    Observe implementation of polymorphism is complicated by requirements of multiple [implementation] inheritance. Did we

    content ourselves with single inheritance an object would always have a single vptr and we would never need to make any

    adjustments to this.

    Question: Do we face the same complications while implementing multiple interface inheritance? As a starting point consider

    memory layouts of objects of a class that implements multiple interfaces or realizes an interface that multiply inherits from

    other interfaces.

    Constructor and Destructor Call Order

    Object construction involves allocating memory for the object and initializing its contents [and acquiring outside resources, if

    needed] by means of a call to the relevant constructor. This atomic sequence is triggered on three conditions:

    A variable with static extent is defined: In the case of a global variable, memory for the object is allocated in the static

    data region at compile time and constructor call [that is, initialization and resource acquisition] is executed as the firststatement of the program. If there is more than one such variable, constructors are executed in the order in which the

    corresponding definitions occur in the text. Static local variables differ in two aspects: call to the constructor is executed

    once upon first entry to the function and this call does not modify the order of statement execution in the function.

    1.

    A block variable is defined: Both allocation and initialization take place at run-time each time control flow reaches the

    point of the variable definition.

    2.

    An object is created using the new operator: Object is allocated and initialized as the control flow reaches the statement

    where the new operator is applied.

    3.

    Example: Construction order of variables with static extent.

    cl ass C {publ i c: C( voi d) { cout

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    40/48

    voi d f( voi d) { cout

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    41/48

    del et e o3; }. . .

    . . . I n t he C1 constructor t ak i ng an i nt . . . i = 3 / / for o3 I n t he defaul t const ructor of C1 / / f or o I n t he C1 constructor t ak i ng an i nt . . . i = 1 / / for o1 I n t he C1 constructor t ak i ng an i nt . . . i = 2 / / for o2

    I n t he dest r uctor of C1. . . i = 3 / / f or o3 I n t he dest r uctor of C1. . . i = 2 / / f or o2 I n t he dest r uctor of C1. . . i = 1 / / f or o1 I n t he dest ructor of C1.. . i = 138645 / / f or o . . .

    An Object Composed of Sub-object(s)

    In the process of creating a composite object, a call to the constructor [of the composite object] is preceded by the relevant

    constructor call(s) for the sub-object(s). Unless these calls are explicitly made in the member initialization list, sub-objects are

    initialized using the default constructor(s).

    Example:

    cl ass C2 {publ i c: C2( voi d) { cout

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    42/48

    }. . .

    . . . I n t he defaul t const ructor of C1 / / f or o. _o1 I n t he defaul t const ructor of C1 / / f or o. _o2 I n t he defaul t const ructor of C3 / / f or o I n t he dest ructor of C3 / / f or o I n t he dest ructor of C1 / / f or o. _o2 I n t he dest ructor of C1 / / f or o. _o1 . . .

    Creating an Array of Objects

    A facility to define group of variables belonging to the same type, an array variable is initialized by initializing each and every

    one of its components. Similarly, destroying this array requires destruction of each and every one of its components.

    Example:

    cl ass C2 {

    publ i c: C2( voi d) { cout

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    43/48

    . . . I n t he defaul t const ructor of C1 / / f or o. _o[0] I n t he defaul t const ructor of C1 / / f or o. _o[1] I n t he defaul t const ructor of C4 / / f or o I n t he dest ructor of C4 / / f or o I n t he dest ructor of C1 / / f or o. _o[1] I n t he dest ructor of C1 / / f or o. _o[0] . . .

    Example:

    cl ass C5 {publ i c: C5( voi d) { cout

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    44/48

    publ i c: C1 _c1_part ; pri vat e:

    . . . I n t he defaul t const ructor of C1 / / f or C1 part of o1 I n t he defaul t cons t r uctor o f I C1 / / f o r o1 I n t he dest ructor of I C1 / / f or o1 I n t he dest ructor of C1 / / f or C1 part of o1 . . .

    Example: Inheritance and composition.

    cl ass I C2 : publ i c C1 {publ i c: I C2( voi d) { cout

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    45/48

    For pedagogical purposes, line 4 of the above fragment can be seen as the following. However, since it replaces two sequences

    of "an initialization followed by an assignment" with two initializations, using a member initialization list is a more efficient

    choice. This is becauseeven when you don't have a member initialization listconstructor(s) of the sub-objects are called

    before that of the composite object, which means the two lines in the following fragment are actually assignments, not

    initializations. [9]Before> they get executed each sub-object will have already been initialized using the default constructor of

    C1.

    I C3( i nt i ) { _c1_part = C1( 1) ; _o = C1( 1) ;

    . . . I n t he C1 constructor t ak i ng an i nt / / for C1 part of o1 I n t he C1 constructor t ak i ng an i nt / / f or o1. _o I n t he I C3 const ructor tak i ng an i nt / / f or o1 I n t he dest ructor of I C3 / / f or o1 I n t he dest ructor of C1 / / f or o1. _o I n t he dest ructor of C1 / / f or C1 part of o1 . . .

    Multiple Inheritance

    Building on our informal definition of inheritance as compiler-managed composition we can treat objects of multiply inheriting

    classes as being composed of more than one sub-object. Therefore, for pedagogical purposes, we can accordingly consider line

    1 of the following fragment as below.

    cl ass I C4 {publ i c: C1 _c1_par t ; C2 _c2_par t ;

    Example:

    c l ass I C4 : publ i c C1, publ i c C2 {1.

    publ i c:2.

    I C4( vo id) { cout < "I n the defaul t const ructor of I C4"

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    46/48

    . . . I n t he defaul t const ructor of C1 / / for C1 par t of o1 I n t he defaul t const ructor of C1 / / f or _o of t he C2 par t of o1 I n t he defaul t const ructor of C2 / / for C2 par t of o1 I n t he defaul t cons t r uctor o f I C4 / / fo r o1 I n t he dest r uctor of I C4 / / f or o1 I n t he dest ructor of C2 / / f or C2 par t of o1 I n t he dest ructor of C1 / / f or _o of t he C2 par t of o1 I n t he dest ructor of C1 / / f or C1 par t of o1 . . .

    Restating the Formula: Inheritance is Compiler-Managed Composition

    What follows are three pairs of equivalent class definitions meant to provide an insight into what the compiler accomplishes

    behind the scenes. While perusing through the code keep in mind that code given in the right column reflects only what the

    compiler does, not how it does it.

    cl ass SC1 { . . . ; publ i c: . . . ;

    voi d SC1_f 1( . . . ) ; voi d SC1_f 2( . . . ) ; . . . ; }; / / end of cl ass SC1

    Public inheritance enables use of base class interfaces through that of the derived class. No effort is required on the

    programmer side, all is taken care of by the compiler. If for some reason you want to do it without inheritance, you must

    explicitly expose the functions of the base class and delegate calls to these functions to the corresponding functions in the base

    class. With private inheritance and selective exposition of the base class interface, this extra burden is lessened for C++

    programmers.

    cl ass DC1 : publ i c SC1 {

    . . . ;publ i c: . . . ; / / voi d SC1_f1( . . . ) ; / / voi d SC1_f2( . . . ) ; . . . DC1_f 1( . . . ) ; . . . DC1_f 2( . . . ) ; . . . ;}; / / end of cl ass DC1

    cl ass CC1 {

    publ i c: / / publ i c! ! ! SC1 _o; / / SC1 partpri vat e: . . . ;publ i c: . . . ; voi d SC1_f 1( . . . ) { _o. SC1_f 1( . . . ) ; } voi d SC1_f 2( . . . ) { _o. SC1_f 2( . . . ) ; } . . . CC1_f 1( . . . ) ; . . . CC1_f 2( . . . ) ; . . . ;}; / / end of cl ass CC1

    Private derivation means the functionality in the base class is not visible through an object of the derived class. However, it is

    still possible to utilize this functionality in implementing the functions found in the interface of the derived class.

    cl ass DC2 : pri vat e SC1 { . . . ;publ i c: . . . ; . . . DC2_f 1( . . . ) ; . . . DC2_f 2( . . . ) ; . . . DC2_SC1_f 1( . . . ) { . . . ; t hi s- >SC1_f 1( . . . ) ; . . . ; } / / end of . . . DC2_SC1_f 1( . . . ) . . . DC2_SC1_f 2( . . . ) { . . . ; t hi s- >SC1f 2( . . . ) ; . . . ;

    cl ass CC2 { SC1 _o;

    . . . ;publ i c: . . . ; . . . CC2_f 1( . . . ) ; . . . CC2_f 2( . . . ) ; . . . CC2_SC1_f 1( . . . ) { . . . ; _o. SC1_f 1( . . . ) ; . . . ; } / / end of . . . CC2_SC1_f 1( . . . ) . . . CC2_SC1_f 2( . . . ) {

    gramming Language Concepts Using C and C++/Object Orientation a... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...

    f 48 20-11-2014 13:08

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    47/48

    } / / end of . . . DC2_SC1_f 2( . . . ) . . . ;}; / / end of cl ass DC2

    . . . ; _o. SC1_f 2( . . . ) ; . . . ; } / / end of . . . CC2_SC1_f 2( . . . ) . . . ;}; / / end of cl ass CC2

    Sometimes a mixture of the two cases may be needed. That is; part of the functionality in the base class is visible and rest has

    to to be hidden. This selective exposition can be accomplished by a combination of private inheritance and the usi ngdeclaration.

    cl ass DC3 : pri vat e SC1 { . . . ;publ i c: usi ng SC1: : SC1_f 2; . . . ; . . . DC3_f 1( . . . ) ; . . . DC3_f 2( . . . ) ; . . . DC3_SC1_f 1( . . . ) { . . . ; t hi s- >SC1_f 1( . . . ) ; . . . ; } / / end of . . . DC3_SC1_f 1( . . . )

    . . . ;}; / / end of cl ass DC3

    cl ass CC3 { SC1 _o; . . . ;publ i c: voi d CC3_SC1_f 2( . . . ) { _o. SC1_f 2( . . . ) ; } / / end of voi d CC3_SC1_f 2( . . . ) . . . ; . . . CC3_f 1( . . . ) ; . . . CC3_f 2( . . . ) ;

    . . . CC3_SC1_f 1( . . . ) { . . . ; _o. SC1_f 1( . . . ) ; . . . ; } / / end of . . . CC3_SC1_f 1( . . . ) . . . ;}; / / end of cl ass CC3

    Virtual Inheritance

    Object of a virtual base class is always constructed prior to the objects of non-virtual classes. It should be kept in mind that

    "virtualness" is actually the property of the derivation, not that of the base class itself.

    Example:

    cl ass VC2 : publ i c vi r t ual C1 {publ i c: VC2( voi d) { cout

  • 8/10/2019 14 Programming Language Concepts Using C and C++_Object Orientation and Inheritance in C++ - Wikibooks, o

    48/48

    . . .{ VC4 o; . . . ;}. . .

    . . . I n the defaul t const ructor of C1 I n t he defaul t constr uct or of VC2 I n t he defaul t constr uct or of VC3 I n t he defaul t constr uct or of VC4 I n the destr uctor of VC4 I n the destr uctor of VC3 I n the destr uctor of VC2 I n t he destr uctor of C1 . . .

    Notes

    One other option would be to make use of the code generation aspect of Java annotations.1.

    The only thing that lacks in this picture is garbage-collection. A partial solution to this will be provided by means of

    smart pointers, which will be introduced in the implementation part.

    2.

    Reuse is usually taken to be code reuse. However, analysis and design documents, program code, test cases and test

    code are all candidates for reuse. As a matter of fact, reuse of artifacts from the early stages of the software production

    process has a larger impact on productivity.

    3.

    We can achieve the same result by defining the common message protocol in an interface and get classes to implement

    this interface.

    4.

    Notice it is once again dynamic dispatch that makes the magic work. It is not known which method the compar emessage will be dispatched to until the program is run and line 6 is executed. Use of pointer-to-function in the equivalent

    C code of Callback section in the Sample C Programs chapter is a testimony to this.

    5.

    Unlike other contexts where the word "polymorphism" passes, the function callby matching the arguments with the

    signature of the functionis resolved at compile- or link-time and therefore statically dispatched.

    6.

    For instance, some architectures do not allow the goto instruction into the body of another function.7.

    Destructor invocations of dynamically allocated objects take place at the point of the relevant application of del et e.8.This belies our definition of a constructor, which states that a constructor is used to initialize an object. As far as C++

    is concerned, what takes place in a constructor is assignment; initialization is made using the member initialization list.

    9.

    Retrieved from "http://en.wikibooks.org/w/index.php?title=Programming_Language_Concepts_Using_C_and_C%2B%2B

    /Object_Orientation_and_Inheritance_in_C%2B%2B&oldid=2718898"

    This page was last modified on 28 October 2014, at 12:46.

    Text is available under the Creative Commons Attribution-ShareAlike License.; additional terms may apply. By using thissite, you agree to the Terms of Use and Privacy Policy.

    gramming Language Concepts Using C and C++/Object Orientation a... http://en.wikibooks.org/wiki/Programming_Language_Concepts_Using...