1 / 35

159.234 LECTURE 15

159.234 LECTURE 15. Inheritance. Text book p.273-298. Inheritance. We frequently classify objects according to some common properties. Mammals have properties such as: warm-blooded higher vertebrates

hankse
Download Presentation

159.234 LECTURE 15

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. 159.234LECTURE 15 Inheritance • Text book p.273-298

  2. Inheritance • We frequently classify objects according to some common properties. • Mammals have properties such as: • warm-blooded • higher vertebrates • These properties are valid for both an elephant and a mouse, but it is best if we only have to express it only once for all mammals and not have to duplicate for every mammal. • Using inheritance, a large body of knowledge can be presented in a more compact way.

  3. Inheritance living creatures mammal reptile elephant cat snake The class cat is derived from the class mammal. We say that a cat “is amammal” and is also a “living creature”. But a cat “is not a reptile”. It is often useful to build our Object-Oriented programs this way.

  4. Inheritance Parent, or base class Shape Child, or derived class TwoD ThreeD Sphere Circle Rectangle How can we code our objects like this?

  5. #include <iostream> using namespace std; const static double PI = 3.141592654; class Shape{ // base class private: char * label; // a string label for the shape }; class TwoD : public Shape{ // two dimensional shapes private: double x, y; }; class ThreeD : public Shape{ // three dimensional shapes private: double x, y, z; }; class Circle : public TwoD{ // Circle extends TwoD public: double area() { return PI * radius * radius; } private: double radius; }; class Rectangle : public TwoD{ public: double area(){ return width * height; } private: double width, height; }; class Sphere : public ThreeD{ public: double volume() { return 4.0 / 3.0 * PI * radius * radius * radius; } private: double radius; }; int main(){ Sphere s1; Circle c1; Shape* shptr; shptr = & s1; shptr = & c1; return 0; } No output - this is only a skeleton code!. Note the public inheritance relations between the classes. Shape is the base class, and TwoD and ThreeD are derived from it We can group information (and avoid having to duplicate code) in a way that reflects our application and the real things or ideas that our code models. Note that in main, a Shapepointercan point to any object that is derivedfrom it.

  6. Inheritance For the parent (of class Circle) we might write: class TwoD : public Shape{ public: void print(){cout<< x;} //... protected: double x,y; //... }; protected: the data of the class is accessible from within the class itself, to its friend classes, derived classes and their friend classes (derived classes’ friend classes), but not in any other part of the program.

  7. Inheritance For the parent class of Circle we write: class TwoD :public Shape{ public: void print(){cout<<…;} //.. protected: double x, y; //.. }; For the derived class we write: class Circle:public TwoD{ public: double area(); private: double radius; }; public print()and protected xandy, are now also part of Circle(inherited from the parent).

  8. Inheritance class Circle :public TwoD{ public: double area(); private: double radius; }; This is called public inheritance. publicandprotecteddata of the parent class are inherited in the derived class, and have the same access type. We can have private and protected inheritance as well - we will look at those later. Public inheritance is the most commonly used. Next, let’s modify the hierarchy of classes we saw earlier...

  9. #include <iostream> using namespace std; const static double PI = 3.141592654; class Shape{ // base class private: char * label; // a string label for the shape }; class TwoD : public Shape{ // two dimensional shapes protected: double x, y; }; class ThreeD : public Shape{ // three dimensional shapes protected: double x, y, z; }; class Circle : public TwoD{ // Circle extends TwoD public: double area(){ return PI * radius * radius; } private: double radius; }; class Rectangle : public TwoD{ public: double area(){ return width * height; } private: double width, height; }; class Sphere : public ThreeD{ public: double volume() { return 4.0 / 3.0 * PI * radius * radius * radius; } private: double radius; }; int main(){ Sphere s1; Circlec1; cout << "size of s1 is " << sizeof(s1) << endl; cout << "size of c1 is " << sizeof(c1) << endl; return 0; } Example Output: size of s1 is 36+4 size of c1 is 28+4 40 = 4 (char *) + 3 * 8 (double) + 8 (double) + 4 (Class) 32 = 4 (char*) + 2 * 8 (double) + 8 (double)+ 4 (Class) Circles inherit labeland x and y Spheres inherit label, x, yand z class incurs an extra overhead

  10. Inheritance: Visibility Modifiers Public inheritance: public in base -> public in derived protected -> protected private -> cannot be accessed Protected inheritance: public in base -> protected in derived protected -> protected private -> cannot be accessed Private inheritance: public in base -> private in derived protected -> private private -> cannot be accessed Default inheritance if not explicitly specified: private

  11. Inheritance We can create a new type Grad from Stud with added information : class Grad:publicStud{ public: Grad(char *s, int id, char *t); void print(); protected: char thesis[64]; }; class Stud { public: Stud(char *s, int id); void print(); protected: intstud_id; char surname[64]; }; Notice that each class has its own constructor.

  12. Inheritance Stud:: Stud(char *s, int id) { strcpy(surname,s); stud_id = id; } Grad::Grad(char *s, intid, char *t) :Stud(s, id) { strcpy(thesis, t); } How do we get initialisation of the information? The constructor for Stud is placed in the initialiser list of the Gradconstructor.

  13. Inheritance It is possible to redefine functions (override) in the derived class to alter its behaviour. print() is defined in both Stud and Grad. void Stud::print() { cout << surname << " " << stud_id; } void Grad::print() { Stud::print(); cout << " " << thesis; } We must use the scope operator, otherwise we get a recursive call. Which function is used is decided at compile time - depending on the type of the object.

  14. Inheritance If we have many objects derived from the type TwoD and need to calculate their total area: We could store pointersto them in an array. Then work through the array to calculate the total area. Circlec, d; Recte, f; TwoD *p[4]; p[0]=&c; p[1]=&d; p[2]=&e; p[3]=&f; This is allowed because Circleand Rectare both derived from TwoD.

  15. Inheritance Now loop through the array: for (inti=0;i<4;i++) { total += p[i]->area(); } Does this work? Yes, if we create virtual functions!

  16. Polymorphism class TwoD { public: TwoD(double a, double b) : x(a), y(b) {} virtual double area(void) {return 0;} protected: double x,y; }; area() is a called a virtual function.

  17. Polymorphism class Rect: public TwoD{ public: Rect(double a, double b, double ht, double wd) : TwoD(a,b), h(ht), w(wd) {} virtual double area(void) {return w * h;} private: double h,w; }; area() is a called a virtual function.

  18. Polymorphism class Circle: public TwoD{ public: Circle(double a, double b, double rad) : TwoD(a,b), r(rad) {} virtual double area(void) {return PI*r*r;} private: double r; }; area is a called a virtual function.

  19. Polymorphism area() is called a virtualfunction. The run-time system knows the types of objects that pointers point to! The appropriate function is called when we ask for p[i]->area() Here’s the code segment again: Circle c, d; Rect e, f; TwoD* p[4]; p[0]=&c; p[1]=&d; p[2]=&e; p[3]=&f; for (inti=0;i<4;i++) { total += p[i]->area(); } This is called dynamic binding. The binding of the call to the actual code to be executed is deferred until run-time.

  20. Destructors Be careful with derived objects created on the heap using new/delete. If we delete an object through a base-class pointer delete p[i]; Then only the destructor of the base class will be called! Not unless it is declared virtual. As a general rule, if a base class contains virtual functions, then the destructor in the base class should also be virtual. See Virtual Destructor - Memory Leak Resolved.cpp

  21. Abstract Base Classes Sometimes we want to declare a class, but only allow a programmer to create objects of its derived classes. TwoDcan be made into an abstract class. We can create objects of its derived classes, circleand rect. We can create pointers to the TwoDclass. But, we can not create an object of type TwoD. The compiler will not allow an object to be created if a class contains a 'pure virtual function'.

  22. Pure Virtual Function class TwoD { public: TwoD(double a, double b) : x(a), y(b) {} virtual double area(void) = 0; protected: double x, y; };

  23. Multiple Inheritance Derived classes can have more than one base class: class Student { public: char name[32]; char id[10]; ... }; class Worker { public: char name[32]; char ird_no[13]; ... }; class Lab_Tutor: public Student, public Worker { ... };

  24. Inheritance The scope operator is used to resolve name clashes. Lab_TutorA; strcpy(A.Student::name, “Napoleon"); ...

  25. Virtual Inheritance If we want to remove the ambiguity, we can make the inheritance 'virtual'. class Person { public: char name[32]; }; or public virtualPerson class Student : virtual public Person { public: char id[10]; ... };

  26. Virtual Inheritance class Person { public: char name[32]; }; class Worker : virtual public Person { public: char ird_no[13]; ... }; class Student : virtual public Person { public: char id[10]; ... }; class Lab_Tutor : public Student, public Worker { ... }; Now there is only one name associated with Lab_Tutor: Lab_TutorA; strcpy(A.name, “Itchy"); ...

  27. Sample Codes • See Demo Codes: • virt_err.cpp • virt_sel2.cpp • abstract.cpp

  28. #include <iostream> using namespace std; class B { public: virtual void foo(int i) {cout<<"\n In Base " << i;} virtual void foo(double d){cout<<"\n In Base "<< d;} }; class D : public B { public: void foo(int k) {cout<<"\n In derived " <<k;} }; int main(){ D d; B b, *pb = &d; b.foo(9); //selects B::foo(int); b.foo(9.5); //selects B::foo(double); d.foo(9); //selects D::foo(int); d.foo(9.5); //selects D::foo(int); // here, the function foo() in class //d is called because we are accessing //the object directly pb -> foo(9); //selects D::foo(int); pb -> foo(9.5); //selects B::foo(double); return 0; } Output: In Base 9 In Base 9.5 In derived 9 In derived 9 In derived 9 In Base 9.5 virt_err.cpp

  29. #include <iostream> using namespace std; //virtual function selection class B { public: int i; virtual //comment this out-see what is the result! void print_i() const { cout << i << " inside Base class" << endl; } }; class D : public B { public: //virtual as well void print_i() const { cout << i << " inside Derived class" << endl; } }; int main() { Bb; B* pb = &b; //points at a B object D f; D& g=f; f.i = 1 + (b.i = 1); pb -> print_i(); //call B::print_i() pb = &f; //points at a D object pb -> print_i(); //call D::print_i() g.print_i(); //call D::print_i() } Output: 1 inside Base class 2 inside Derived class 2 inside Derived class virt_sel2.cpp

  30. #include <iostream> using namespace std; //virtual function selection class B { public: inti; void print_i() const { cout << i << " inside Base class" << endl; } }; class D : public B { public: void print_i() const { cout << i << " inside Derived class" << endl; } }; int main() { Bb; B* pb = &b; //points at a B object D f; D& g=f; f.i = 1 + (b.i = 1); pb -> print_i(); //call B::print_i() pb = &f; //points at a D object pb -> print_i(); //call D::print_i() g.print_i(); //call D::print_i() } Output (non-virtual): 1 inside Base class 2 inside Base class 2 inside Derived class

  31. Let’s take a peek at how the compiler is actually implementing virtual inheritance.

  32. Virtual Inheritance ColorListStruct ColorListStruct Base Table Source: Efficient C/C++ Coding Techniques Embedded Systems Conference Boston 2001 Class 304 No classes actually contain the virtual base class. Instead, they hold a pointer to a virtual base class table that tells them where in the object the virtual base class exists.

  33. Multiple Virtual Inheritance Source: Efficient C/C++ Coding Techniques Embedded Systems Conference Boston 2001 Class 304 Each level of virtual inheritance requires its own virtual base table.

  34. Additional References Technical Report on C++ Performance ISO/IEC TR 18015:2006(E) Mastering Visual C++ http://www.cplusplus.com/reference/iostream/ios/bad.html Efficient C/C++ Coding Techniques Embedded Systems Conference Boston 2001 Class 304 Next: Inheritance

  35. Summary Inheritance is the mechanismof deriving new classes from old ones. Through inheritance, a hierarchy of related, code-sharing abstract data types (ADT’s) can be created. The keywords public, private, and protected are used as visibility modifiers for class members. Next: More on inheritance Abstract classes

More Related