Top Banner
1 159.234 159.234 LECTURE 15 LECTURE 15 Inheritance Inheritance Text book p.273-298
35

1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

Jan 05, 2016

Download

Documents

Arnold Cummings
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

1

159.234159.234 LECTURE 15LECTURE 15

InheritanceInheritance

Text book p.273-298

Page 2: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

2

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.

InheritanceInheritance

Page 3: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

3

The class catcat is derived from the class mammal.We say that a cat “is a mammal” 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.

mammal

elephant

reptile

snakecat

living creatures

InheritanceInheritance

Page 4: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

4

Sphere

Shape

TwoD ThreeD

Circle Rectangle

Parent, or base class

Child, or derived class

How can we code our objects like this?How can we code our objects like this?

InheritanceInheritance

Page 5: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

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!.skeleton code!.

Note the public inheritance public inheritance relations between the classes.

Shape is the base classbase class, and TwoD and ThreeD are derivedderived 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 Shape pointer can point to any object that is derivedderived from it.

Page 6: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

6

For the parentparent (of class Circle) we might write:

class TwoD : public Shape{ public: void print(){cout<< x;} //... protectedprotected: double x,y; //...};

protectedprotected: : 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.

InheritanceInheritance

Page 7: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

7

For the parent class of Circle we write:

class TwoDTwoD :public Shape{ public: void print()print(){cout<<…;} //.. protected: double x, yx, y; //..};

For the derived class derived class we write:

class CircleCircle :public TwoD:public TwoD{ public: double area(); private: double radius;};

public print()print() and protected xx and yy, are now also part of CCircleircle (inherited from the parent).

InheritanceInheritance

Page 8: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

8

This is called public inheritancepublic inheritance.

publicpublic and protectedprotected data 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.

class Circle :public TwoD :public TwoD { public: double area(); private: double radius;};

InheritanceInheritance

Next, let’s modify the hierarchy of classes we saw earlier...

Page 9: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

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; Circle c1;

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+4size 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 labellabel and xx and yySpheres inherit labellabel, x, yx, y and zz

class incurs an extra overhead

Page 10: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

10

Inheritance: Inheritance: Visibility ModifiersVisibility Modifiers

Public inheritance:public in base -> public in derivedprotected -> protectedprivate -> cannot be accessedcannot be accessed

Protected inheritance:public in base -> protected in derivedprotected -> protectedprivate -> cannot be accessedcannot be accessed

Private inheritance:public in base -> private in derivedprotected -> privateprivate -> cannot be accessedcannot be accessed

Default inheritance if not explicitly specified: privateprivate

Page 11: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

11

InheritanceInheritance

class StudStud {public: Stud(char *s, int id); void print();

protected: int stud_id; char surname[64];};

We can create a new type Grad from Stud with added information :

class GradGrad : publicpublic StudStud {public: Grad(char *s, int id, char *t); void print();

protected: char thesis[64];};

Notice that each class has its own constructor.

Page 12: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

12

InheritanceInheritance

Stud:: StudStud(char *s, int id) { strcpy(surname,s); stud_id = id;}

Grad::GradGrad(char *ss, int idid, char *t) :: StudStud(s, id)(s, id) { strcpy(thesis, t);}

The constructor for Stud is placed in the initialiser list initialiser list of the GradGrad constructor.

How do we get initialisation of the information?

Page 13: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

13

InheritanceInheritance

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::printprint() { cout << surname << " " << stud_id;}

void Grad::printprint() { Stud::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.

Page 14: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

14

InheritanceInheritance

If we have many objects derivedderived from the type TwoDTwoD and need to calculate their total area:

We could store pointerspointers to them in an array.

Then work through the array to calculate the total area.

CircleCircle c, dc, d; RectRect e, fe, f; TwoDTwoD *pp[4];

pp[0]=&cc; pp[1]=&dd; pp[2]=&ee; pp[3]=&ff;

This is allowed because CircleCircle and RectRect are both derivedderived from TwoDTwoD.

Page 15: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

15

InheritanceInheritance

Now loop through the array:

for (int i=0;i<4;i++) { total += pp[i]->area()area();

}

Does this work?

Yes, if we create virtual functions!

Page 16: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

16

PolymorphismPolymorphism

class TwoDTwoD {public: TwoD(double a, double b) : x(a), y(b) {} virtualvirtual double areaarea(void) {return 0;return 0;}

protected: double x,y;};

area()area() is a called a virtual virtual function.

Page 17: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

17

PolymorphismPolymorphism

class RectRect : public TwoDTwoD{public: RectRect(double a, double b, double ht, double wd) : TwoDTwoD(a,b), h(ht), w(wd) {} virtualvirtual double area(void) {return w * h;return w * h;}

private: double h,w;};

area()area() is a called a virtual virtual function.

Page 18: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

18

PolymorphismPolymorphism

class CircleCircle : public TwoDTwoD{public: Circle(double a, double b, double rad) : TwoD(a,b), r(rad) {} virtualvirtual double area(void) {return PI*r*r;return PI*r*r;}

private: double r;};

area is a called a virtual function.

Page 19: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

19

PolymorphismPolymorphism

area() is called a virtualvirtual function.

The run-time system knows the types of knows the types of objects that pointers objects that pointers point topoint to!

The appropriate function is called when we ask for p[i]->area()p[i]->area()

for (int i=0;i<4;i++) { total += p[i]->area()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;

This is called dynamic bindingdynamic binding. The binding of the call to the actual code to be executed is deferred until run-time.

Page 20: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

20

DestructorsDestructors

Be careful with derivedderived objects created on the heap using new/deletenew/delete..

If we delete an object through a base-class pointer

delete p[i];delete p[i];

Then only the destructor of the base class base class will be called! Not unless it is declared virtualvirtual.

As a general rule, if a base class base class contains virtual functionsvirtual functions, then the destructordestructor in the base class should also be virtualshould also be virtual.

See Virtual Destructor - Memory Leak Resolved.cpp

Page 21: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

21

Abstract Base ClassesAbstract Base Classes

Sometimes we want to declare a class, but only allow a programmer to create objects of its derived classes.

TwoDTwoD can be made into an abstract class. We can create objects of its derived classes, circlecircle and rectrect. We can create pointers to the TwoDTwoD class. But, we can not create an object of type TwoDTwoD .

The compiler will not allow an object to be created if a class contains a 'pure virtual function'pure virtual function'.

Page 22: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

22

PurePure Virtual Function Virtual Function

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

Page 23: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

23

Multiple InheritanceMultiple Inheritance

class Student {public: char namename[32]; char id[10];...};

class Worker {public: char namename[32[32]; char ird_no[13];...};

class Lab_TutorLab_Tutor : public Student, public Worker {...};

Derived classes can have more than one base class:

Page 24: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

24

InheritanceInheritance

Lab_TutorLab_Tutor A; strcpy(A.Student::A.Student::name, “Napoleon"); ...

The scope operator is used to resolve name clashes.

Page 25: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

25

Virtual InheritanceVirtual Inheritance

If we want to remove the ambiguityto remove the ambiguity, we can make the inheritance 'virtual'.

class Person { public: char name[32];};

class Student : virtual public Person { public: char id[10]; ...};

or public virtual Person

Page 26: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

26

Virtual InheritanceVirtual Inheritance

class Worker : virtual public Person {public: char ird_no[13]; ...};

class Lab_Tutor : public Student, public Worker {...};

Now there is only one name associated with Lab_Tutor:

Lab_Tutor A;strcpy(A.namename, “Itchy");...

class Person { public: char name[32];};

class Student : virtual public Person { public: char id[10]; ...};

Page 27: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

27

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

Sample CodesSample Codes

Page 28: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

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;}

virt_err.cpp

Output:

In Base 9 In Base 9.5 In derived 9 In derived 9 In derived 9 In Base 9.5

Page 29: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

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() { B b; B* pb = &b; //points at a B object D f; D& g=f;

f.i = 1 + (b.i = 1);

pb -> print_i(); //call BB::print_i() pb = &f; //points at a DD object pb -> print_i(); //call DD::print_i() g.print_i(); //call DD::print_i() }

virt_sel2.cppOutput:1 inside Base class2 inside Derived class2 inside Derived class

Page 30: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

30

Output (non-virtual):1 inside Base class2 inside Base class2 inside Derived class

#include <iostream>using namespace std;//virtual function selection

class B {public: int i; 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() { B b; B* pb = &b; //points at a B object D f; D& g=f;

f.i = 1 + (b.i = 1);

pb -> print_i(); //call BB::print_i() pb = &f; //points at a DD object pb -> print_i(); //call DD::print_i() g.print_i(); //call DD::print_i() }

Page 31: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

31

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

Page 32: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

32

Virtual InheritanceVirtual Inheritance

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.

ColorListStruct

ColorListStruct Base Table

Source: Efficient C/C++ Coding Techniques Embedded Systems Conference Boston 2001 Class 304

Page 33: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

33

Multiple Virtual InheritanceMultiple Virtual Inheritance

Each level of virtual inheritance requires its own virtual base table.

Source: Efficient C/C++ Coding Techniques Embedded Systems Conference Boston 2001 Class 304

Page 34: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

Additional References

34

Technical Report on C++ Performance ISO/IEC TR 18015:2006(E)

Next: Inheritance

Mastering Visual C++

http://www.cplusplus.com/reference/iostream/ios/bad.html

Efficient C/C++ Coding Techniques Embedded Systems Conference Boston 2001 Class 304

Page 35: 1 159.234LECTURE 15 159.234 LECTURE 15 Inheritance Text book p.273-298.

35

Inheritance is the mechanism of 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 inheritanceAbstract classes

SummarySummary