Object oriented programming
This presentation is the property of its rightful owner.
Sponsored Links
1 / 46

Object Oriented Programming PowerPoint PPT Presentation


  • 52 Views
  • Uploaded on
  • Presentation posted in: General

Object Oriented Programming. Egar 2008 Recitation 9. Private / Protected Inheritance. Why?. Unlike public inheritance (that means “is-a”), private and protected inheritance mean “has-a” or “is-implemented-in-terms-of”.

Download Presentation

Object Oriented Programming

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.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Object oriented programming

Object Oriented Programming

Egar 2008

Recitation 9

OOP Etgar 2008 – Recitation 9


Private protected inheritance

Private/Protected Inheritance

OOP Etgar 2008 – Recitation 9


Object oriented programming

Why?

  • Unlike public inheritance (that means “is-a”), private and protected inheritance mean “has-a” or “is-implemented-in-terms-of”.

  • They are quite similar to composition (when an inner object is contained as data member in the outer object), but there are subtle differences.

OOP Etgar 2008 – Recitation 9


Composition

Composition

  • Inner object is called data member.

  • Data member can be accessed from outside only if declared public.

  • Outer object can’t override data member’s methods or access protected members.

  • Outer object can contain several data members of one type.

OOP Etgar 2008 – Recitation 9


Private protected inheritance1

Private/Protected Inheritance

  • Inner object is called base class subobject.

  • Subobject cannot be accessed from outside (and derived pointer cannot be converted to private/protected base pointer, unless by methods or friends of the derived).

  • Derived can access protected members of the subobject.

  • Derived can override subobject’s methods.

  • Outer object contains only one base class subobject.

OOP Etgar 2008 – Recitation 9


Code example

Code Example

  • class B {

  • public:void pub();

  • protected:void prot();

  • private:void priv();

  • };

  • class pubD: public B{…};

  • class protD: protected B{…};

  • class privD: private B{…};

OOP Etgar 2008 – Recitation 9


Access levels

Access Levels

  • public inheritance:

    • public parts of B remain public in pubD and protected remain protected in pubD.

  • protected inheritance:

    • public and protected parts of B become protected in protD.

  • private inheritance:

    • public and protected parts of B become private in privD.

  • B’s private remains inaccessible to derived.

OOP Etgar 2008 – Recitation 9


When to use

When to Use?

  • Use composition whenever you can.

  • Use private/protected inheritance when you have to:

    • If you need to override inherited virtual method.

    • If you need access to protected members.

OOP Etgar 2008 – Recitation 9


Multiple inheritance

Multiple Inheritance

OOP Etgar 2008 – Recitation 9


Object oriented programming

Why?

  • Recall the interface Shape from previous lecture and imagine we have class MyCircle that implements circles (but not with Shape’s interface).

  • We would like to implement a Circle with Shape’s interface while using existing code from MyCircle.

  • Usually this is done with composition, but what if private inheritance is required?

OOP Etgar 2008 – Recitation 9


Multiple inheritance1

Multiple Inheritance

  • In C++ we can use multiple inheritance – make a class inherit from more than one base.

    • class Circle: public Shape, private MyCircle {…};

  • Circle now has Shape’s interface and all features of private inheritance from MyCircle.

  • Class can inherit from any number of bases and in any combination of public/protected/private inheritance.

  • OOP Etgar 2008 – Recitation 9


    Points

    Points

    • Pointer or reference to derived can be implicitly converted to any of the bases.

      • Conversion to each base is considered equally good.

    • Subclass constructor initializes base classes in the order of their appearance from left to right (and destructor destroys in the reverse order).

    OOP Etgar 2008 – Recitation 9


    Ambiguities

    Ambiguities

    • What if two bases define functions with the same name?

      • class Shape{ public: virtual void draw(); };

      • class MyCircle{ public: void draw(); };

      • class Circle: public Shape, private MyCircle {…};

      • // Circle doesn't redefine draw()

      • Circle c;

      • c.draw();// Ambiguous – Shape::draw() or

      • MyCircle::draw()?

    OOP Etgar 2008 – Recitation 9


    Overload resolution

    Overload Resolution?

    • Even if draw()’s parameter list were different in bases, the call still would have been ambiguous.

    • This is because overload resolution is not applied across different class scopes.

    OOP Etgar 2008 – Recitation 9


    Ambiguity resolution

    Ambiguity Resolution

    • To resolve this ambiguity we can:

      • Use explicit qualification

        • c.Shape::draw();

  • Use the using-declaration

    • class Shape…{

    • using Shape::draw;

    • };

    • c.draw();// Calls c.Shape::draw()

  • OOP Etgar 2008 – Recitation 9


    Virtual bases

    Virtual Bases

    OOP Etgar 2008 – Recitation 9


    The dreaded diamond

    The Dreaded Diamond

    • Continuing the Shape hierarchy:

      • class OnScreenObj {protected : Screen _scr…};

      • class Shape: public OnScreenObj {…};

      • class Text: public OnScreenObj {…};

      • class TextArt: public Shape, public Text {…};

  • This poses a problem – in multiple inheritance each base is represented by its own subobject.

  • But we don’t want the Shape part of TextArt to have different _scr than the Text part!

  • OOP Etgar 2008 – Recitation 9


    Another ambiguity

    Another Ambiguity

    • Moreover, since TextArt has two OnScreenObj parts, we must specify which one we mean:

      • TextArt ta;

      • ta._scr;// Ambiguous – which _scr?

      • ta.Shape::_scr;// Ok

      • ta.Text::_scr;// Ok

      • ta.Text::OnScreenObj::_scr; // Ok

    OOP Etgar 2008 – Recitation 9


    Virtual inheritance

    Virtual Inheritance

    • To specify that derived classes of Shape or Text can share one copy of the base OnScreenObj, we can define it as virtual base:

      • class Shape: public virtual OnScreenObj {…};

      • class Text: virtual public OnScreenObj {…};

      • class TextArt: public Shape, public Text {…};

  • Now TextArt has only one OnScreenObj subobject.

  • OOP Etgar 2008 – Recitation 9


    Initialization

    Initialization

    • In regular inheritance, each class initializes its immediate base classes.

    • With virtual inheritance, the most derived class must initialize it.

    OOP Etgar 2008 – Recitation 9


    Initialization example

    Initialization Example

    • For example, A is a virtual base of B, D (regularly) derives from B, E from D and F from E.class B : virtual public Aclass D : public Bclass E : public Dclass F : public E

    • When object of type B is created, A is initialized from B’s constructor, when object of type D is created – from D’s, and so on.

    • Thus B, D, E, F‘s constructors must initialize A.A::A(int a=1):_a(a){}B::B(int a=1,b=2):A(a),_b(b){} D::D(int a=1,b=2,d=3):A(a),B(a,b){}E::E(int a=1,b=2,d=3,e=4):A(a),b(a,b),d(a,b,d){}…

    • Note that all virtual base classes are created before all other base classes.

    OOP Etgar 2008 – Recitation 9


    Multiple inheritance alternatives

    Multiple Inheritance Alternatives

    • Consider the following situation:Suppose you have land vehicles, water vehicles, air vehicles, and space vehicles .

    • Suppose we also have different power sources: gas powered, wind powered, nuclear powered, pedal powered, etc.

    • We could use multiple inheritance to tie everything together, but before we do, we should ask a few tough questions:

    • Will the users of LandVehicle need to have a Vehicle& that refers to a LandVehicle object? In particular, will the users call methods on a Vehicle-reference and expect the actual implementation of those methods to be specific to LandVehicles?

    • The same question for for GasPoweredVehicles.

    OOP Etgar 2008 – Recitation 9


    Multiple inheritance alternatives1

    Multiple Inheritance Alternatives

    • if both answers are "yes," multiple inheritance is probably the best way to go.

    • If none or one of the answers are “no” consider the following alternatives.

    • Also there are some considerations which will make you choose an alternative even if both answers are “yes”.

    • The alternatives are the bridge pattern and nested generalization.

    OOP Etgar 2008 – Recitation 9


    The bridge pattern

    The Bridge Pattern

    • We create two distinct hierarchies:

    • ABCVehicle has derived classes LandVehicle, WaterVehicle, etc.

    • ABCEngine has derived classes GasPowered, NuclearPowered, etc.

    • Then the Vehicle has an Engine* (that is, an Engine-pointer), and users mix and match vehicles and engines at run-time.

    OOP Etgar 2008 – Recitation 9


    Nested generalization

    Nested Generalization

    • We pick one of the hierarchies as primary and the other as secondary, and you have a nested hierarchy.

    • For example, if you choose geography as primary, Vehicle would have derived classes LandVehicle, WaterVehicle, etc.

    • Those would each have further derived classes, one per power source type. E.g., LandVehicle would have derived classes GasPoweredLandVehicle, PedalPoweredLandVehicle, NuclearPoweredLandVehicle, etc.

    OOP Etgar 2008 – Recitation 9


    Exceptions

    Exceptions

    Error-handling mechanism

    OOP Etgar 2008 – Recitation 9


    Object oriented programming

    Why?

    • Consider what happens when an error occurs in a program that consists of separate modules.

    • Often the action that needs to be taken depends on the calling module rather than on the module that found the error.

      • A string doesn’t know what to do if it cannot allocate memory. The user of the string does.

    • And what if the caller of the caller knows how to fix the error?

    OOP Etgar 2008 – Recitation 9


    Exceptions1

    Exceptions

    • Exceptions are program anomalies that occur during runtime (out-of-memory, pop-on-empty-stack, division-by-zero, etc.).

    • Exception handling is a mechanism that allows two separately developed modules to communicate when exception occurs.

    OOP Etgar 2008 – Recitation 9


    Throwing and catching

    Throwing and Catching

    • A module that detects an error has occurred signals it by throwing an exception of appropriate type.

    • The module in the calling chain that knows how to handle the exception declares that by catching an exception of that type.

      • A pop() in Stack can throw popOnEmpty, and Stack’s user can catch it and know that pop() didn’t succeed because it’s empty.

    OOP Etgar 2008 – Recitation 9


    Why exceptions

    Why Exceptions?

    • Exceptions:

      • Separate exceptional logic from normal logic.

      • Supported by the compiler.

      • Can carry any amount of information from thrower to the catcher.

      • Can be used in constructors.

    • But impose runtime overhead.

    • Returning error codes is still used.

    OOP Etgar 2008 – Recitation 9


    Throw

    throw

    • An exception is an object of some type.

    • The program part that has detected an error that it cannot handle, throws an exception (which is an object) of some type.

    • This is done using the throw expression.

    OOP Etgar 2008 – Recitation 9


    Example

    Example

    • class popOnEmpty {};// Exceptions are objects,

    • class pushOnFull {};// need to define the classes

    • int Stack::pop() {// Stack from recitation 1

    • if (_top_index == 0)

    • throw popOnEmpty();// Used to be "return 0"

    • return _contents[--_top_index];

    • }

    • void Stack::push(int el) {

    • if (_top_index == _size)

    • throw pushOnFull();// Used to be "return false"

    • _contents[_top_index++] = el;

    • return true;

    • }

    OOP Etgar 2008 – Recitation 9


    Example notes

    Example Notes

    • Notice that now push() doesn’t return a value, and pop() returns only elements of the stack.

    • Since throw throws an object, the corresponding class needs to be defined beforehand.

    • It’s best to use separate classes for exceptions.

    OOP Etgar 2008 – Recitation 9


    Throw creates an object

    throw Creates an Object

    • throw creates a temporary object of the given type and “passes it on”.

      • Note the () in

        • throw pushOnFull();

  • This creates a pushOnFull object using the default constructor.

  • Had class pushOnFull had a constructor with int parameter (for example), we could write:

    • throw pushOnFull(el);

  • The handler would then know what element wasn’t pushed.

  • OOP Etgar 2008 – Recitation 9


    Catching

    Catching

    • To be handled, an exception needs to be caught.

    • This is done using try-catch construct.

    • Operations that can throw exception are enclosed in a try block, and following that block a series of catch clauses, each defining how to handle specific type of exception.

    OOP Etgar 2008 – Recitation 9


    Example1

    Example

    • int main() {

    • Stack s(10);

    • try {

    • s.push(1);

    • // More pops, pushes, printouts, etc.

    • } catch (popOnEmpty) {

    • cout << "Caught popOnEmpty\n";

    • } catch (pushOnFull) {

    • cout << "Caught pushOnFull\n";

    • }

    • cout << "Done\n";

    • return 0;

    • }

    OOP Etgar 2008 – Recitation 9


    Catch clauses

    catch Clauses

    • Each catch clause defines how to handle a specific type of exception that might have occurred in the preceding try block.

    • The clauses are examined top down until a matching catch is found.

    • If none is found, the exception propagates to the caller.

    • If a matching catch clause is found, its body is executed and execution resumes after the last catch (for that try block).

    OOP Etgar 2008 – Recitation 9


    Exception propagation

    Exception Propagation

    • Notice that a try-catch block only needs to handle exceptions it knows how to “fix”.

    • Anything is doesn’t handle propagates to the caller of that function.

    • When exception tries to propagate out of main(), the STL terminate() function is called, which by default calls abort().

    OOP Etgar 2008 – Recitation 9


    Exception declaration

    Exception Declaration

    • The () part in catch is called exception declaration.

    • It can be either type declaration or an object declaration.

      • …catch (popOnEmpty) {// Type declaration

      • cout << "Caught popOnEmpty\n";

      • } catch (pushOnFull e) {// Object declaration

      • cout << e.val() << " cannot be pushed\n";

      • }

  • In object declaration the exception object that was thrown is given a name and can be accessed.

  • This allows the exception object to carry additional information about the error.

  • OOP Etgar 2008 – Recitation 9


    Catching everything

    Catching Everything

    • If someone (main(), for example) wants to handle any exception that can be thrown, it can use catch(...):

      • try {

      • //…

      • } catch (...) {

      • cout << "Unknown exception occurred\n";

      • }

  • Obviously, it should come last in the list of catches.

  • OOP Etgar 2008 – Recitation 9


    Catching by reference

    Catching by Reference

    • Exception declaration is much like function parameter list.

    • In particular, we can catch exception objects by reference:

      • …catch (pushOnFull& e) {…}

  • Otherwise the exception object is passed by-value into the catch clause.

  • Using “catch-by-reference”:

    • Prevents unnecessary copying;

    • Allows changing the exception object;

    • Permits polymorphism.

  • OOP Etgar 2008 – Recitation 9


    Exception specification

    Exception Specification

    • How do we know which function throws exceptions and what types?

    • Function exception specification is a comma-separated list of exceptions the function might throw.

      • int Stack::pop() throw(popOnEmpty);

      • void Stack::push(int) throw(pushOnFull);

  • This list is checked at runtime – if the function throws unspecified exception, the STL unexpected() function is called (which by default calls terminate()).

  • Exception specification is part of functions interface:

    • int Stack::pop() {// Err, must match declaration

  • OOP Etgar 2008 – Recitation 9


    Stack unwinding

    Stack Unwinding

    • When an exception is thrown, the calling functions exit one after another until a handler is found.

    • During this process all the objects that were defined on stack (local – also called automatic – variables in these functions) are properly destroyed.

    • This is called stack unwinding.

    OOP Etgar 2008 – Recitation 9


    Rethrow

    Rethrow

    • If a handler doesn’t know how to fully recover from an exception, it can rethrow it (after doing what it wanted).

    • This is done by throw;

      • …catch (popOnEmpty e) {

      • cout << "Can't pop";

      • throw;

      • }

  • The object rethrown is the original exception object (not the copy in catch).

  • OOP Etgar 2008 – Recitation 9


    Exception hierarchies

    Exception Hierarchies

    • Since exceptions are objects, we can build exceptions hierarchies.

    • For example, a base class Exception, subclasses StackException and MathException, and two subclasses for StackExceptions – popOnEmpty and pushOnFull.

    • All rules applying to base and derived apply here (catching derived instead of base, virtual functions with “catch-by-reference”, etc.)

    OOP Etgar 2008 – Recitation 9


    Constructors and destructors

    Constructors and Destructors

    • Constructor can (and should) signal an error by throwing an exception.

      • In this case all data members and base class subobjects constructed so far are properly destroyed.

    • Destructor should never throw (or let out) an exception.

      • Destructors are called during stack unwinding, and if it throws another exception (thus two exceptions will be active simultaneously), terminate() is called.

    OOP Etgar 2008 – Recitation 9


  • Login