1 / 41

Comp5421 Object Oriented Programming

Comp5421 Object Oriented Programming. Designing with Inheritance Lecture 5 (1) Tianxiang Shen Summer 2002 Department of Computer Science Concordia university. Designing with Inheritance.

moira
Download Presentation

Comp5421 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. 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. Comp5421 Object Oriented Programming Designing with Inheritance Lecture 5 (1) Tianxiang Shen Summer 2002 Department of Computer Science Concordia university Concordia TAV 2002 Comp5421_51

  2. Designing with Inheritance • Inheritance is the Hierarchical arrangement of classes so that some properties of a class (base) can be inherited by other (derived) class. • It is one of the central features of OOD and OOP. (textbook p105) • Its presence in object-oriented languages provides a framework for both organizing and implementing a system. • It provides a way to simplify programming and a foundation for reusing code by letting the code of the super-class be shared by all its subclasses. • It offers the ability to refine and extend existing code, through virtual methods. • It offers an organizational structure for code, documenting similar items using the class-subclass relationship. • Provide a basis for describing the varying behavior of different entire in a system. Concordia TAV 2002 Comp5421_51

  3. Base and Derived Classes • Base and derived classes • Often an object from a derived class (subclass) is also an object of a base class (superclass) • A rectangle is a derived class in reference to a quadrilateral and a base class in reference to a square • Inheritance examples Concordia TAV 2002 Comp5421_51

  4. Base and derived class class Person //inh1.cpp { public: Person(char* n="", int s=0, char* nat="U.S.A.") : name(n), sex(s), nationality(nat) { } void setDOB(int m, int d, int y) { dob.setDate(m, d, y); } void setDOD(int m, int d, int y) {dod.setDate(m, d, y); } void printName() { std::cout << name; } void printNationality() { std::cout << nationality; } void printDOB() { std::cout << dob; } void printDOD() { std::cout << dod; } protected: std::string name, nationality; Date dob, dod; // date of birth, date of death int sex; // 0=female, 1=male }; Concordia TAV 2002 Comp5421_51

  5. Base and derived class class Student : public Person{ public: Student(char* n, int s=0, char* i="") : Person(n,s), id(i), credits(0) { } void setDOM(int m, int d, int y) { dom.setDate(m, d, y); } void printDOM() { std::cout << dom; } void printSex() { std::cout << (sex ? "male" : "female");} private: std::string id; // student identification number Date dom; // date of matriculation int credits; // course credits float gpa; // grade-point average }; int main(){ Student x("Ann Jones", 0 , "2131341414"); x.setDOB(5,13,1977); x.setDOM(8,29,1995); x.setDOB(7,4,1826); x.printName(); std::cout<<"\n\t Born: "; x.printDOB(); std::cout<<"\n\t Sex: "; x.printSex(); std::cout<<"\n\t Matriculated: "; x.printDOM(); std::cout<< "\n"; return 0; } Concordia TAV 2002 Comp5421_51

  6. Defining a derived class Concordia TAV 2002 Comp5421_51

  7. Friend Function • Friend function is a nonmember function that is given access to all members of the class within which it is declared. • It does not have a this pointer because it is not a member of the class. • It has all the privileges of a member function without actually being a member of the class. • It is used mostly with overloaded operators. • Include the friend function’s prototype in the public section of a class declaration. Concordia TAV 2002 Comp5421_51

  8. Friend Function • When an operator function is implemented as a member function, the leftmost (or only) operand must be a class object (or a reference to a class object) of the operator’s class. • If the left operator must be an object of a different class or a built-in type, this operator function must be implemented as a non-member function (as the stream-insertion << and stream-extraction >> operators) Concordia TAV 2002 Comp5421_51

  9. Friend Function • Stream insertion operator << and stream extraction operator >> cannot be declared as member functions (because their first operand is a reference to a stream) they are declared as friend function • Example: // Write a vector to output stream. • friend ostream & operator<< (ostream & os, Vector v); • ostream & operator<< (ostream & os, Vector v) • { os << '(' << v[0] << ',' << v[1] << ',' << v[2] << ')'; • return os; • } Concordia TAV 2002 Comp5421_51

  10. Friend Function • (Example: complex.cpp) • class Complex • { • private: int real; • int imag; • public: Complex(int r=0, int i=0){real=r; imag=i;} • void show(){cout<<real<<"+"<<imag<<"i";} • friend Complex operator+(Complex, Complex); • }; • Complex operator+ (Complex a, Complex b) • { int r= a.real + b.real; • int i= a.imag + b.imag; • return Complex(r,i); • } • Note: • 1. Friend is not used in the function implementation • 2. Scope resolution prefix Vector:: is not used because it is not a member function Concordia TAV 2002 Comp5421_51

  11. Public Inheritance (public.cpp) Member Access from • Undeclared identifier • Is not a member of base class • An object only can access its public member • All public and protected members of base class become public and protected members of derived class. • Private of base is inaccessible for derived class Concordia TAV 2002 Comp5421_51

  12. Protected Inheritance (protected.cpp) Member Access from 1. Access is protected: All public and protected members become protected members of the derived class, so case 1 public of base becomes protected member of the derived class. Concordia TAV 2002 Comp5421_51

  13. Private Inheritance (private.cpp) Member Access from 1. Access is private: All public and protected members of the class become private members of the derived class, so case 1, the public of base becomes private member of the derived class. Concordia TAV 2002 Comp5421_51

  14. Access specifier • General form: class ClassName: access BaseClassName{…} • Access is public: all public and protected members of base class become public and protected members of derived class. 2. Access is private: all public and protected members of the class become private members of the derived class. 3. Access is protected: all public and protected members become protected members of the derived class. Concordia TAV 2002 Comp5421_51

  15. Static Function Member • Static member function is used to access only static data from their own class. • Static member function has no “this” pointer, it is independent of the individual objects of the class. Example: class Widget { public: Widget() { ++count; } ~Widget() { --count; } static int num() { return count; } private: static int count; }; int Widget::count = 0; int main() { cout << "Now there are " << Widget::num() << " widgets.\n"; Widget w, x; cout << "Now there are " << Widget::num() << " widgets.\n"; { Widget w, x, y, z; cout << "Now there are " << Widget::num() << " widgets.\n"; } cout << "Now there are " << Widget::num() << " widgets.\n"; Widget y; cout << "Now there are " << Widget::num() << " widgets.\n"; }

  16. Access Control 1. Private: only non-static member function and friend function of the same class have access to the feature; • Protected: only non-static member function, friend function of the same class and its derived classes have access to the features, that is, its members are accessible from within the class itself, its friend class, its derived classes, and their friend classes; • Public: its membersare accessible from anywhere within the file. Note: Example of the friend class: class Window; class Screen{ friend class Window; //… } /*nonpublic members of class Screen may be accessed within each of the Window member functions */ Concordia TAV 2002 Comp5421_51

  17. Access specifier Concordia TAV 2002 Comp5421_51

  18. Overriding inherited member • If function f() is defined in base class X, and another f() with same signature is defined in derived class Y, then objY.a will access latter data member, and objY.X::a will access former. We say the a defined in Y dominates the a defines in X. objY.f() invokes the latter function, and objY.X::f() invokes the former. In this case, local function yobj.f() overrides the f() defined in X. • Example: overriding.cpp class X { public: void f() { cout << "X::f() executing\n"; } int a; }; class Y : public X { public: void f() { cout << "Y::f() executing\n"; } // overrides X::f() int a; // overrifes X::a }; Concordia TAV 2002 Comp5421_51

  19. Overriding inherited member int main(){ X x; x.a = 22; x.f(); cout << "x.a = " << x.a << endl; Y y; y.a = 44; // assigns 44 to the a defined in Y y.X::a = 66; // assigns 66 to the a defined in X y.f(); // invokes the f() defined in Y y.X::f(); // invokes the f() defined in X cout << "y.a = " << y.a << endl; cout << "y.X::a = " << y.X::a << endl; X z = y; cout << "z.a = " << z.a << endl; } /* X::f() executing x.a = 22 Y::f() executing X::f() executing y.a = 44 y.X::a = 66 z.a = 66 */ Concordia TAV 2002 Comp5421_51

  20. Overriding inherited member • This diagram illustrates the three objects x, y, and z: • Here, y has access to two different data members a and two different functions f(). Defaults are the ones defined in the derived class Y. Scope resolution operator :: is used in X:: to override the default to access the corresponding members defined in the parent class X. When X object z is initialized with y, its X members are used: z.a is assigned the value y.X::a. Concordia TAV 2002 Comp5421_51

  21. Parent Constructor and Destructor • Each constructor invokes its parent constructor before executing itself. • Each destructor invokes its parent constructor after executing itself. • Example: class X { public:X() { cout << "X::X() constructor executing\n"; } ~X() { cout << "X::X() destructor executing\n"; } }; class Y : public X { public: Y() { cout << "Y::Y() constructor executing\n"; } ~Y() { cout << "Y::Y() destructor executing\n"; } }; class Z : public Y { public: Z(int n) { cout << "Z::Z() constructor executing\n"; } ~Z() { cout << "Z::Z() destructor executing\n"; } }; int main(){ Z z(44); } Concordia TAV 2002 Comp5421_51

  22. Polymorphism and Virtual Function • Polymorphism is a language mechanism that permit the same interface to invoke different functions or operators depending upon the type of objects using the interface. Example: To draw the various shapes, we can declare a generic Shape class, • It is achieved by means of virtual function. • It is realized possible by the fact that a pointer to a base class instance may also point to any subclass instances. Concordia TAV 2002 Comp5421_51

  23. Virtual function (1) • How to invoke f() in derived class Y by pointer to X? (virtual1.cpp) class X{ public: void f() { cout << "X::f() executing\n"; } }; class Y : public X{ public: void f() { cout << "Y::f() executing\n"; } }; int main(){ X x; Y y; X* p = &x; // p has type X* (pointer to type X) // It’s statically defined type X* of p p->f(); // invokes X::f() because p has type X* p = &y; p->f(); // invokes X::f() because p has type X* } /* X::f() executing X::f() executing */ Concordia TAV 2002 Comp5421_51

  24. Virtual function (2) • Why do both calls invoke the same version of f() that is defined in base class X? Because p is statically bound to the base class function at compile time. Even when p is pointing to an instance of a subclass Y, its type is still X*, so p->f() would invoke the function f() defined in the base class. • Iftransform X::f() into a virtual function by adding the keyword “virtual” to its declaration: class X //Ex1210b.cpp { public: virtual void f(){ cout << "X::f() executing\n"; } }; With the rest of the code left unchanged, the output now become: /* X::f() executing Y::f() executing */ Now the second call p->f() invokes Y::f() instead of X::f(). Concordia TAV 2002 Comp5421_51

  25. Virtual function (3) • When virtual is added to f() in X, the function is selected according to which class of object p pointer to. This is called dynamic binding because the binding of the call to the actual code to be executed is deferred until run time. • The rule (that the pointer’s statically defined type determines which member function gets invoked) is overruled by declaring the member function Virtual Concordia TAV 2002 Comp5421_51

  26. Pure virtual function • Pure virtual function is a virtual function that no implementation in its class, that is, the virtual function is certain to be overridden in its subclasses, then there is no need to implement it all in its base class. • A pure virtual function cannot be called in the class in which it is defined. • Syntax: virtual type f() = 0; Example: pureVirtual.cpp Concordia TAV 2002 Comp5421_51

  27. Abstract Class • Abstract base class is a class that has one or more pure virtual functions. 1. An abstract class cannot have instances by its own without binding/linking to derived classes. (If it had instances, it would be possible to invoke a pure virtual function, leading to disaster.) 2. It also cannot be used as function parameter types or as return types. 3. However, you can create a pointer to an abstract class. 4. A class inherits an abstract and does not override all of the pure virtual functions will, itself, be abstract. • Concrete derived class is a class that does not have any pure virtual functions. 5. A derived class must override all pure functions of all of its base classes before, the derived class become concrete and objects of its class can be created. Concordia TAV 2002 Comp5421_51

  28. Example Aircraft (Base class) • Example: a small airline that organizes its aircraft using an inheritance hierarchy: Aircraft, Jet, jumbo, and stretch. class Aircraft{ Public: Aircraft (); int length (); int Profit (double dist); int revenue (double dist); int expense (double dist); double basicRate (); virtual int capacity (double dist) = o; virtual int price (double dist) = o; virtual consumption ( int numberPassengers) = 0; protected: int lengthAircraft; }; Concordia TAV 2002 Comp5421_51

  29. Aircraft class (base class) • Aircraft::Aircraft() //constructor { lengthAircraft = 100; } • lnt Aircraft::lengthl () { retucn lengthAircraft; } • Three pure virtual methods: capacity(), Price(), consumption() of class Aircraft • int Aircraft::profit (double dist) { cout << “Aircraft profit" << endl; return revenue(dist) - expense(dist); } • int Aircraft::revenue(double dist) { cout << "Aircraft revenue" << endl; return capacity(dist) * price(dist); } Concordia TAV 2002 Comp5421_51

  30. Aircraft class (base class) int Aircraft::expense(double dist) { cout << "Aircraft expense" << endl: return dist * consumption(capacity(dist)); } double Aircraft::basicRate () { cout << "Aircraft basicRate " << endl: return 0.1; // dollars per kilometer } Concordia TAV 2002 Comp5421_51

  31. Jet class (derived class from Aircraft class) • //Declaration for class Jet class Jet: public Aircraft { public: int capacity (double dist); int price (double dist); int consumption(int numberPassengers); }; • //Function definitions for class Jet; int Jet::capacity(double dist) { cout << “Jet capacity” << end1; return int(350.0 * (1.0 - dist / 7500.0)) } int Jet::price(double dist) { cout << "Jet price’ <<endl; return int(basicRate() * dist); } int Jet::consumption (int numberPassengers) { cout << “Jet consumption” << endl; return 100 + numberPassengers / 4; } Concordia TAV 2002 Comp5421_51

  32. Jumbo class (derived from Jet class) • //declaration for Jumbo class class jumbo:public Jet { public: Jumbo ( ); int capacity(double dist); int consumption(int numberPassengers); } • //Function definitions for class Jumbo; Jumbo::Jumbo() { lengthAircraft = 120; } int Jumbo::capacity(double dist) { cout << "Jumbo capacity" << endl; return int(500.0 * (1.0 - dist / 15000.0)); } int Jumbo::consumption(int numberPassengers) { cout << "Jumbo consumptlon" << endl; retucn 150 + numberPassengers / 5; } Concordia TAV 2002 Comp5421_51

  33. Stretch class (derived from Jumbo class) • //Declaration for class Stretch class Stretch:public jumbo { public: Stretch(); int price(double dist); }; • //Function definitions for class stretch: Stretch::Stcetch() { lengthAircraft = 140; } int Stretch::price( double dist) { cout << "Stretch price” << endl; return int(2.0 * basicRate() * dist); } Concordia TAV 2002 Comp5421_51

  34. Avoidduplication • Inheritance avoids duplication: The function length() is declared and defined in the class Aircraft, and used in all derived classes. Suppose we declare Jet a; Jumbo b; The following expressions a.length(); b.length(); would execute the length() of Aircraft, and may give different results, depending on the value of lengthAircraft in the class of the receiver. Concordia TAV 2002 Comp5421_51

  35. Function cab be redefined in derived classes • Function can be redefined in derived classes: Example: Function capacity ( ) is declared as pure virtual function. So, capacity() can be inherited and redefined in the derived classes: (for number of passengers) capacity of a Jet = 350 * (1- dist/7500); capacity of Jumbo = 500 * (1 – dist/15000) Stretch has no capacity() function, it will inherit its parent Jumbo one Concordia TAV 2002 Comp5421_51

  36. Base class functions can call derived class functions • Virtual function mechanismallows us to write code ina base class that calls functions in derived classes. (baseCallDerived.cpp) • Example: Base class function expense( ) uses two functions capacity( ) and consumption( ) that are declared as pure virtual function in class Aircraft and are only defined in the derived classes. • Evaluation of the expression: Jumbo jumbo; //jumbo is an instance of class Jumbo jumbo.expense(2000.0) //call base class function expense Running result: Aircraft expense Jumbo capacity Jumbo consumption jumbo expense = 472000 • Similarly, for revenue and profit base class functions Concordia TAV 2002 Comp5421_51

  37. Derived class functions can call base class function • Derived class functions can call base class function as normal (see page 11-13) • Example: Function price() is a pure virtual function in base class Aircraft, it is redefined in derived classes. The redefined function price() in Stretch class can call base class function basicRate(). Stretch stretch; cout<<“stretch’s profit = “ << stretch.ptofit(2000.0)<<endl; Running result: Aircraft profit Aircraft revenue Jumbo capacity Stretch price Aircraft basicRate Aircraft expense Jumbo capacity Jumbo consumption stretch profit = -298800 • In a large and complex program such calls can be difficult to understand and trace, often referred as "yoyo problems". Concordia TAV 2002 Comp5421_51

  38. Function binding can occur at run-time • Dynamic function binding can occur at run-time for virtual function: void main( ) { const int FLEET_SIZE = 3; Aircraft *fleet [FLEET_SIZE]; fleet[0] = new Jet; fleet[1] = new Jumbo; fleet[2] = new Stretch; while (true) { cout << "Enter distance (<= 0 terminates): " ; double distance; cin >> distance; if (distance <=0.0) break; for ( int i = 0; i < FLEET_SIZE i++) { int capacity = fleet [i]->capacity(distance); double profit = fleet[i]->profit(distance); // function called depend upon type of // object that fleet[I] points to cout << “Plane” << i <<“carries” << capacity <<“ passengers with a ”; if (profit >= 0.0) cout << "profit of $" << profit <<endl; else cout << "loss of $" << -profit <<endl; } // for loop } // While loop } // main • Since compiler cannot determine what type fleet[i] is, the name of the function must be matched to its definition while program is running. This is called Dynamic binding. Concordia TAV 2002 Comp5421_51

  39. Function binding can occur at run-time (2) • Program reports the functions used in each computation. Here is a report generated by the program. Note that the range of 7500 km is too long for a jet and unprofitable for a jumbo. (Results are dependent on version on the web.) Enter distance (<= 0 terminates): 7500 Jet capacity Aircraft profit Aircraft revenue Jet capacity Jet price Aircraft basicRate Aircraft expense Jet capacity Jet consumption Plane 0 carries 0 passengers with a loss of $750000. … Plane 2 carries 250 passengers with a profit of $1.5e+006. Concordia TAV 2002 Comp5421_51

  40. Conclusions • Advantages: 1. Code reuse: can derive a new class from an existing base class. 2. Reduce code duplication by allowing common code to be moved to base classes. General functions appear near the root of the class hierarchy and more specialized function appear near the leaves. 3. Can build program incrementally. Concordia TAV 2002 Comp5421_51

  41. Conclusions • Potential disadvantages: 1. Dynamic binding slows the program down. 2. Calling constructors and destructors slows the program down. Calling a constructor (or destructor) in a derived class potentially calls constructors (or destructors) in every class above the derived class in the class hierarchy. 3. Code can be hard to understand and trace. The main problem is dynamic binding. Concordia TAV 2002 Comp5421_51

More Related