1 / 36

Introduction to Inheritance and Class Hierarchies

Learn about the basics of inheritance, class hierarchies, member function overriding and overloading, and polymorphism. Also explore abstract classes, assignment, and casting in a hierarchy.

Download Presentation

Introduction to Inheritance and Class Hierarchies

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. 3.1 Introduction to Inheritance and Class Hierarchies 3.2 Member Function Overriding, Member Function Overloading, and Polymorphism 3.3 Abstract Classes, Assignment, and Casting in a Hierarchy 09 – Inheritance

  2. Attendance Quiz #8 Inheritance (09)

  3. Tip #9: Default Arguments Inheritance (09) • Default function parameters supply values when a user does not. int add(int x, int y = 1) { return x + y; } int main() { int result1 = add(5); int result2 = add(5, 3); return 0; } int add(int x, int y) { return x + y; } int main() { int result1 = add(5); // Error int result2 = add(5, 3); return 0; } • Advantages and Disadvantages. • In 99% of cases you don't need half of the function parameters. • With normal functions, default parameters can make code harder to read. • When refactoring, default parameters can be used to add functionality without breaking code. • Introduces problems reviewing or using code written by others - hidden parameters. • Some functions tend to have the same parameter values - default parameters supply those common values and also helps you see the "suggested" value. • **NOTE: google's coding style suggests avoiding them.

  4. Lab 02 - SNAP

  5. S.N.A.P Lab Inheritance (09) • Class design is type design - defining effective classes can be challenging. • For the SNAP lab you are to design classes for a school database with has-a and is-a relationships that have natural syntax, intuitive semantics, and efficient memory allocation. • The class objects are populated from parsed input strings. • Use object inheritance, polymorphism, and function and operator overloading where needed. • All member data and internal functions are private. • All classes have a "toString" method with friends for the insertion ("<<") operator. • Use UML diagrams to describe your implementation.

  6. Example SNAP Output Inheritance (09) Input Strings: snap(12345,Charlie Brown,Manager,555-1234). snap(67890,Lucy,Right Field,555-5678). csg(CS101,12345,A). csg(CS101,67890,B). **Error: csgs(CS101,67890,B). cdh(CS101,M,9AM). cdh(CS101,W,9AM). cr(CS101,1170 TMCB). Vectors: snap(12345,Charlie Brown,Manager,555-1234) snap(67890,Lucy,Right Field,555-5678) csg(CS101,12345,A) csg(CS101,67890,B) cdh(CS101,M,9AM) cdh(CS101,W,9AM) cr(CS101,1170 TMCB) Course Grades: CS101,Charlie Brown,A CS101,Lucy,B Student Schedules: Charlie Brown, 12345, Manager, 555-1234 CS101 MW 9AM, 1170 TMCB Lucy, 67890, Right Field, 555-5678 CS101 MW 9AM, 1170 TMCB Student # Name Address Phone # Course Student # Grade Course Day Hour Course Room Input Error List in csg order List in snap order List in csg order

  7. Student # Name Address Phone # Course Student # Grade Course Day Hour Input Error Course Room List in csg order List in snap order List in csg order

  8. vector<Snap> snaps; vector<Csg> csgs; vector<Cdh> cdhs; vector<Cr> crs; string toString() const { stringstream out; out << "snap(" << this->studentId; out << "," << this->studentName; out << "," << this->studentAddress; out << "," << this->studentPhone << ")"; return out.str(); } friend std::ostream& operator<< (ostream& os, const Snap& snap) { os << snap.toString(); return os; }

  9. UML Inheritance (09) This class is called Passenger. The data members are all listed by visibility, name, and type. Visibility: A '-' in front of a data member or function means that the data or function is private. A '+' indicates public visibility and a '#' indicates a protected visibility Type: You may indicate parameter type and return type before or after the name of the data member/function. Both of the following are acceptable: +string getName() +getName():string Private Public Class Name Data Members Class Methods

  10. UML Inheritance (09) This class is called Passenger. The data members are all listed by visibility, name, and type. Visibility: A '-' in front of a data member or function means that the data or function is private. A '+' indicates public visibility and a '#' indicates a protected visibility Type: You may indicate parameter type and return type before or after the name of the data member/function. Both of the following are acceptable: +string getName() +getName():string

  11. UML Inheritance ("Is-a") Inheritance (09) In this example, the class Steam Engine inherits from the abstract class Locomotive. It has access to all of the concrete functions of Locomotive, and also defines the abstract functions of Locomotive. Note that not all of the concrete functions from Locomotive are included in SteamEngine. This is because they are accessed through inheritance structure. On the other hand, the abstract functions appear in both places. It is a good practice to show a function both where it is declared and where it is defined. For the interfaces that you will use in this class, it is acceptable to omit the inherited functions from the child class. Inheritance is indicated with a white triangle arrowhead facing the parent class.

  12. UML Inheritance ("Has-a") Inheritance (09) In this example, the class Steam Engine references the class Passenger, placing pointers to Passenger objects inside of its private vector. This relationship is indicated by using a filled diamond arrow. The arrow faces towards the class that "has" the other thing in it. Note: For the purposes of our class, we do not distinguish between having an object and having a pointer to an object. Just use the same type of arrow.

  13. SNAP Inheritance Inheritance (09) SNAP Course Cr Cdh Csg -string course -int studID -string name -string address -string phone -string course -int studID -string grade -string course -string day -string hour -string course -string room +string getCourse() +toString() const +string getCourse() +string getRoom() +toString() const +string getCourse() +int getStudID() +string getGrade() +toString() const +string getCourse() +string getDay() +string getHour() +toString() const +int getStudID() +string getName() +string getAddr() +string getPhone() +toString() const Student -int studID +int getStudID() +toString() const

  14. SNAP Inheritance Inheritance (09) This process is known as refactoringand is often used in object-oriented design. Course Cr Cdh Csg SNAP -string course -int studID -string grade -int studID -string name -string address -string phone -string course -string course -string day -string hour -string course -string room +string getCourse() +toString() const +string getCourse() +string getRoom() +toString() const +string getCourse() +string getDay() +string getHour() +toString() const +string getCourse() +int getStudID() +string getGrade() +toString() const +int getStudID() +string getName() +string getAddr() +string getPhone() +toString() const Student -int studID +int getStudID() +toString() const

  15. 3.1 Introduction to Inheritance and Class Hierarchies Is-a Versus Has-a Relationships A Base Class and a Derived Class Initializing Data Fields in a Derived Class The No-Parameter Constructor Protected Visibility for Base-Class Data Fields 3.1 Introduction to Inheritance and Class Hierarchies

  16. Inheritance and Class Hierarchies Inheritance (09) • Object-Oriented Programming (OOP) enables programmers to reuse previously written code saved as classes' • Code reuse reduces the time required to code new applications'. • Previously written tested and debugged code enables new applications to be more reliable. • In OOP, a programmer can create a similar class by extendingan existing class, rather than by writing an entirely new class. • The new class (called the derived classor subclass) can have additional data fields and member functions. • The derived class inheritsthe data fields and member functions of the original class (called the base class or superclass).multiple parents. • A class hierarchy represents a set of hierarchically organized concepts. • Base classes act typically as interfaces. • Implementation inheritance • Interface inheritance. • If a base class is used as an interface, make it a pure abstract class.

  17. Is-a Versus Has-a Relationships Inheritance (09) • The is-arelationship between classes means that every instance of one class is also an instance of the other class (but not the other way around). • A jet airplane is an airplane, but not all airplanes are jet airplanes. • The jet airplane class is derived from an airplane class. • The is-a relationship is represented in object oriented programming by extending a class. • The has-arelationship between classes means that every instance of one class is or may be associated with one or more instances of the other. • For example, a jet plane has-a jet engine. • The has-a relationship is represented by declaring in one class a data field whose type is another class.

  18. Is-a Versus Has-a Relationships Inheritance (09) • We can combine is-a and has-a relationships • A jet plane is an airplane, and it has a jet engine • The jet airplane inherits all the properties of an airplane. An airplane has atail, so a jet plane does too because it is an airplane. • C++ allows you to capture both the inheritance (is-a) relationship and the has-a relationship: class JetPlane : public Airplane { private: int num_engines; JetEngine jets[4]; // Jet planes may have 4 engines // ... }; The part of the class heading following the colon specifies that JetPlaneis a derived class of Airplane The JetEnginedata field stores information for up to 4 jet engines for a JetPlaneobject.

  19. A Base Class and a Derived Class Inheritance (09) • A computer has a: • manufacturer • processor • RAM • disk • A laptop computer is a kind of computer, so it has all the properties of a computer plus some additional features: • screen size • weight Computer -manufacturer:string -processor:string -ramSize:int -diskSize:int • We can define class LapTop as a derived class of class Computer. +getRamSize() const:int +getDiskSize() const:int +toString() const:string • "A LapTop is-a Computer" LapTop -screenSize:int -weight:double +getScreenSize() const:int +getWeight() const:double

  20. Class Computer Inheritance (09) Computer.cpp Computer.h There are 4 private data elements common to all computers. #ifndef COMPUTER_H_ #define COMPUTER_H_ #include <string> class Computer { private: std::string manufacturer; std::string processor; int ramSize; int diskSize; public: Computer(const std::string& man, const std::string& proc, int ram, int disk) : manufacturer(man), processor(proc), ramSize(ram), diskSize(disk) {} int getRamSize() const { return ramSize; } int getDiskSize() const { return diskSize; } std::string toString() const; }; #endif #include "computer.h" #include <sstream> using std::ostringstream; using std::string; using std::endl; string Computer::toString() const { ostringstreamsb; sb << "Manufacturer: " << manufacturer << endl << "CPU: " << processor << endl << "RAM: " << ramSize << " Mbs" << endl << "Disk: " << diskSize << " Gbs"; return sb.str(); } Small in-line member functions are included in the .h file (<= 10 lines). Larger class implementations are often found in a corresponding .cpp file.

  21. Class LapTop Inheritance (09) LapTop.h Class LapTopis derived from class Computer and publicly inherits Computer's data members and member functions. #ifndef LAP_TOP_H #define LAP_TOP_H #include <string> #include <sstream> #include "computer.h" using std::string; using std::ostringstream; class LapTop : public Computer { private: int screenSize; double weight; public: LapTop(const string& m, const string& p, int r, int d, int s, double w) : Computer(m, p, r, d), screenSize(s), weight(w) {} int getScreenSize() const { return screenSize; } double getWeight() const { return weight; } }; #endif The constructor for class LapTopmust begin by initializing the four data fields inherited from class Computer. Because those data fields are private to the base class, C++ requires that they be initialized by a base class constructor. In the definition of a constructor of a class, member initializer listspecifies the initializers for direct and virtual base subobjects and non-static data members.

  22. Protected Data Fields Inheritance (09) Computer.h LapTop.h class Computer { private: std::string manufacturer; std::string processor; int ramSize; int diskSize; public: // ... }; class LapTop : public Computer { private: // ... public: void setManufacturer(std::string m) { manufacturer = m; } // ... }; C++ provides a less restrictive form of visibility called protected visibility to allow a derived class to directly access data fields declared in its base class Illegal!! The data fields inherited from class Computerhave private visibility—they can be accessed only within class Computer. class Computer { protected: std::string manufacturer; private: std::string processor; int ramSize; int diskSize; public: // ... }; class LapTop : public Computer { private: // ... public: void setManufacturer(std::string m) { manufacturer = m; } // ... };

  23. Public, Protected, Private Inheritance Inheritance (09) class A { public: int x; protected: int y; private: int z; }; class B : public A { // x is public // y is protected // z is not accessible from B }; class C : protected A { // x is protected // y is protected // z is not accessible from C }; class D : private A { // x is private // y is private // z is not accessible from D }; Classes B, C and D all contain the variables x, y and z. It is just question of access. 'private' is default for classes

  24. 3.2 Member Function Overriding, Member Function Overloading, and Polymorphism Member Function Overriding Member Function Overloading Virtual Functions and Polymorphism 3.2, pgs. 193-203

  25. Member Function Overriding Inheritance (09) Class LapTophave does not have a toString method. #include <iostream> #include <string> #include "lapTop.h" using namespace std; int main(int argc, char* argv[]) { ComputermyComputer("HP", "I5", 16, 500); LapTopyourComputer("Dell", "I7", 32, 1000, 15, 5); cout << endl << "My computer:" << endl << myComputer.toString() << endl; cout << endl << "Your computer:" << endl << yourComputer.toString() << endl; return 0; } My computer: Manufacturer: HP CPU: I5 RAM: 16 Mbs Disk: 500 Gbs Your computer: Manufacturer: Dell CPU: I7 RAM: 32 Mbs Disk: 1000 Gbs Even though yourComputeris of type LapTop, the LapTopfields are not displayed; the call to toString() calls the toString() method inherited from Computer

  26. Member Function Overriding Inheritance (09) LapTop.cpp If class LapTophas its own toString member function, it will overridethe inherited member function and will be invoked by the member function call to toString(). LapTop.h #ifndef LAP_TOP_H #define LAP_TOP_H #include <string> #include <sstream> #include "computer.h" using std::string; using std::ostringstream; class LapTop : public Computer { private: int screenSize; double weight; public: LapTop(const string& m, const string& p, int r, int d, int s, double w) : Computer(m, p, r, d), screenSize(s), weight(w) {} int screenSize() const { return screenSize; } double getWeight() const { return weight; } string toString() const; }; #endif #include "lapTop.h" #include <sstream> using std::ostringstream; using std::string; using std::endl; string LapTop::toString() const { ostringstreamsb; sb << Computer::toString() << endl << "Screen: " << screenSize << " inches" << endl << "Weight: " << weight << " lbs"; return sb.str(); } We still call Computer'stoString member function to output its contents.

  27. Member Function Overriding Inheritance (09) #include <iostream> #include <string> #include "lapTop.h" using namespace std; int main(int argc, char* argv[]) { ComputermyComputer("HP", "I5", 16, 500); LapTopyourComputer("Dell", "I7", 32, 1000, 15, 5); cout << endl << "My computer:" << endl << myComputer.toString() << endl; cout << endl << "Your computer:" << endl << yourComputer.toString() << endl; return 0; } My computer: Manufacturer: HP CPU: I5 RAM: 16 Mbs Disk: 500 Gbs Your computer: Manufacturer: Dell CPU: I7 RAM: 32 Mbs Disk: 1000 Gbs Screen: 15 inches Weight: 5 lbs Now the state of a laptop computer, complete with screen size and weight, is output when calling toString member function for class LapTopwhich overrides the inherited member function of Computer.

  28. Virtual Functions and Polymorphism Inheritance (09) #include <iostream> #include <vector> #include <string> #include "lapTop.h" using namespace std; int main(int argc, char* argv[]) { vector<Computer*> computers; computers.push_back(new Computer("Acer", "I3", 8, 256)); computers.push_back(new LapTop("HP", "I5", 16, 500, 13, 6.5)); for (unsigned int i = 0; i < computers.size(); i++) cout << endl << computers[i]->toString() << endl; return 0; } Manufacturer: Acer CPU: I3 RAM: 8 Mbs Disk: 256 Gbs Manufacturer: HP CPU: I5 RAM: 16 Mbs Disk: 500 Gbs • In C++, a pointer variable of a base-class type (general) can point to an object of a derived-class type (specific): • LapTopobjects are Computerobjects with more features. But, where are the additional data members??

  29. Virtual Functions and Polymorphism Inheritance (09) #include <iostream> #include <vector> #include <string> #include "lapTop.h" using namespace std; int main(int argc, char* argv[]) { vector<Computer*> computers; computers.push_back(new Computer("Acer", "I3", 8, 256)); computers.push_back(new LapTop("HP", "I5", 16, 500, 13, 6.5)); for (unsigned int i = 0; i < computers.size(); i++) cout << endl << computers[i]->toString() << endl; return 0; } class Computer { // ... public: // ... virtual string toString() const; }; Manufacturer: Acer CPU: I3 RAM: 8 Mbs Disk: 256 Gbs Manufacturer: HP CPU: I5 RAM: 16 Mbs Disk: 500 Gbs Screen: 13 inches Weight: 6.5 lbs By changing the declaration of the function toString in the class Computer(in Computer.h) to a virtual function, when it is called through a pointer (or reference) variable the actual member function will be determined at run time and based on the type of the object pointed to (or referenced).

  30. Virtual Functions and Polymorphism Inheritance (09) • Polymorphism is an important concept of OOP. • Polymorphism is the quality of having many forms or many shapes. • Polymorphism enables the program to determine which member function to invoke at run time. class Computer { // ... public: // ... string toString() const; }; class LapTop : public Computer { // ... public: // ... string toString() const; }; int main() { vector<Computer*> computers; computers.push_back(new Computer(...)); computers.push_back(new LapTop(...)); cout computers[1]->toString(); } class Computer { // ... public: // ... virtual string toString() const; }; class LapTop : public Computer { // ... public: // ... virtual string toString() const; }; int main() { vector<Computer*> computers; computers.push_back(new Computer(...)); computers.push_back(new LapTop(...)); cout computers[1]->toString(); } • At compile time, the C++ compiler cannot determine what type of object computers will point to. • At run time, polymorphism and virtual functions allows the program to know which toString function to call. • Use pointers to your objects. • Declare the function in base class virtual. • BTW: It is good practice to include the virtual declaration in the derived classes too for documentation purposes.

  31. 3.3 Abstract Classes, Assignment, and Casting in a Hierarchy Referencing Actual Objects Summary of Features of Actual Classes and Abstract Classes Assignments in a Class Hierarchy Casting in a Class Hierarchy Case Study: Displaying Addresses for Different Countries 3.3, pgs. 203-206

  32. Abstract Classes Inheritance (09) • An abstract classdiffers from an actual class (sometimes called a concrete class) in two respects: • An abstract class cannot be instantiated. • An abstract class declares at least one abstract member function, which must be defined in its derived classes. • An abstract function is a virtual function that is declared but for which no body (definition) is provided. • We use an abstract class in a class hierarchy when • A base class can define attributes and functions that are common to derived classes. • Actual derived classes may have unique as well as shared implementations. • Pure abstract functions must be defined by derived concrete classes.

  33. Abstract Class Food.h Inheritance (09) #ifndef FOOD_H_ #define FOOD_H_ class Food { private: double calories; public: virtual double percent_protein() const = 0; virtual double percent_fat() const = 0; virtual double percent_carbohydrates() const = 0; double get_calories() const { return calories; } void set_calories(double cal) { calories = cal; } }; #endif These three abstract virtual functions impose the requirement that all derived classes implement these functions. (We would expect a different function definition for each kind of food.) A pure virtual function is specified in the class definition by using "= 0;:" in place of the function body.

  34. Referencing Concrete Objects Inheritance (09) • Because class Food is abstract, we can’t create type Food objects, hence the following statement is invalid: Food mySnack(); // compile time error! • We can use a type Food pointer variable to point to an actual object that belongs to a class derived from Food. • If a Vegetable object is derived from Food, then Foodis contained in Vegetable. Vegetable Food • Thus a pointer to Food can be used to reference a Vegetable. The pointer variable mySnack (type pointer-to-Food) is legal: Food* mySnack = new Vegetable("carrot sticks");

  35. Assignments in a Class Hierarchy Inheritance (09) • C++ is what is known as a strongly typed language. • Operands have a type, and operations can be performed only on operands of the same or compatible types. • This includes the assignment operation: l-value = r-value • For the built-in types the r-value must be of the same type as the l-value, or there must be a conversion defined to convert the r-value into a value that is the same type as the l-value. • For class types, the assignment operator may be overridden and overloaded. • Pointer types are an exception: A pointer variable (l-value) that is of type pointer-to-base class may point to a derived object (r-value). • However, the opposite is not legal: Computer* computer = new LapTop( ... ); // Legal LapTop* laptop = new Computer( ... ); // Illegal

More Related