Vous êtes sur la page 1sur 8

Inheritance in C++

A Simple Example Name Class


class Name { private: char * theName; char * theName

A C++ mechanism that facilitates code reuse It allows programmers to enhance existing working classes without modifying the code of these classes

:
setName(...) print() 0 1 n \0

Outline: Motivation and overview Aspects of Inheritance Example Reference: Book, Chapter 15

public: Name(); Name(char * name); Name(Name & r); ~Name(); void setName(char * newName); Name & operator=(Name & r); void print(); };

Must provide copy constructor and overloaded assignment operator (why?)


1 Copyright 2005-2011 Tarek S. Abdelrahman ECE 244 Programming Fundamentals 2 Copyright 2005-2011 Tarek S. Abdelrahman

ECE 244 Programming Fundamentals

Name Class Implementation


Name::Name() { theName = new char [1]; theName[0] = \0 ; } Name::Name(char * name) { theName = new char[strlen(name)+1]; strcpy(theName, name); } Name::~Name() { delete [] theName; }

Name Class Implementation


void Name::setName(char * newName) { delete [] theName; theName = new char[strlen(newName)+1]; strcpy(theName, newName); } void Name::print() { cout << theName << endl; }

Implement the copy constructor and the overloaded assignment operator on your own!
3 Copyright 2005-2011 Tarek S. Abdelrahman ECE 244 Programming Fundamentals 4 Copyright 2005-2011 Tarek S. Abdelrahman

ECE 244 Programming Fundamentals

A Simple Example Contact

Contact Class Definition


#include Name.h class Contact : public Name { private: char * theAddress; public: Contact(); ~Contact(); Contact(Contact & r); Contact(char * newName, char *newAddress): void setNameAddress(char * newName, char * newAddress); Contact & operator=(Contact & r); void print(); };
!

char * theName char * theAddress

n \0

:
Contact 0 1 n \0

char * theName : setName(...) print() char * theAddress : setNameAddress(..) print()

Create a Contact from two char strings: one for the name and the other for the address Set the name in the object/Set the address of the object Print the name and address
5 Copyright 2005-2011 Tarek S. Abdelrahman

! !

Contact inherits from Name its data members as well as its function members (with some exceptions to be seen later)
6 Copyright 2005-2011 Tarek S. Abdelrahman

ECE 244 Programming Fundamentals

ECE 244 Programming Fundamentals

Contact Class Use


main() { Name n; Contact c; n.setName( Tarek Abdelrahman ); n.print(); The print() in Contact overrides (eclipses) the print() inherited from Name

Aspects of Inheritance
class Derived : public Base { : }
! ! ! ! !

What does the Derived class inherit from the Base class? What does the Derived class not inherit from Base? What can the Derived class add? What happens when variables of the Derived class are created? What happens when variables of the Derived class are destroyed? What is the relationship between objects of the Base class and objects of the Derived class? What is the relationship between pointers to objects of the Base class and to objects of the Derived class? What are virtual functions and abstract classes?
8 Copyright 2005-2011 Tarek S. Abdelrahman

c.setName( Tarek Abdelrahman ); c.setNameAddress( John Smith , 123 Main Street ); c.print(); n.setNameAddress( Tarek Abdelrahman , 123 Main Street ); }
!

Data/(most) Function members of Name are data/Function members of Contact Not the other way around
7 Copyright 2005-2011 Tarek S. Abdelrahman

ECE 244 Programming Fundamentals

ECE 244 Programming Fundamentals

What is Inherited?
!

Access to Inherited Members


void Contact::print() { Name::print(); cout << theAddress << endl; }

All the data members of the Base class (both private and public) e.g.: in Contact, theName is inherited from Name

However, private data members of Base are not accessible in Derived e.g.: in Contact, theName is not accessible Use public functions inherited from Name to access theName

We call the print() in Name to print the name part of contact

All the ordinary function members of Base e.g.: in Contact, setName and print() are inherited Contact::print() overrides Name::print()

void Contact::setNameAddress(char * newName; char * newAddress) { setName(newName); delete [] theAddress; theAddress = new char[strlen(newAddress)+1]; strcpy(theAddress, newAddress); } We call the setName() in Name to print the name part of contact
ECE 244 Programming Fundamentals 10 Copyright 2005-2011 Tarek S. Abdelrahman

However, private function members of Base are not accessible in Derived


9 Copyright 2005-2011 Tarek S. Abdelrahman

ECE 244 Programming Fundamentals

What is NOT Inherited?


!

What can be Added by Derived?


!

The constructors and destructor of the Base class e.g.: in Contact, Contact(), ~Contact() etc must be defined Makes no sense otherwise A default constructor is provided if none are defined

New data members (private and public)

e.g.: Contact adds theAddress

! !

New function members (private and public) e.g.: Contact adds setNameAddress and print()

The overloaded assignment operator One is provided by default in Contact

The friends of the Base class We will not focus on friends

Functions in Contact override functions with the same name (signature) in Name

ECE 244 Programming Fundamentals

11

Copyright 2005-2011 Tarek S. Abdelrahman

ECE 244 Programming Fundamentals

12

Copyright 2005-2011 Tarek S. Abdelrahman

Creation of Objects of the Derived Class


! ! !

Contact Class Constructor

The derived object is created The default constructor of the base class is called The constructor of the derived class is called Contact c; 0 \0 char * theName char * theAddress Name(); Contact::Contact() { theAddress = new char [1]; theAddress[0] = \0 ; }

0 \0 Contact();

Allocate only the new data in Contact; assume Name part is already constructed

ECE 244 Programming Fundamentals

13

Copyright 2005-2011 Tarek S. Abdelrahman

ECE 244 Programming Fundamentals

14

Copyright 2005-2011 Tarek S. Abdelrahman

Creation of Objects of the Derived Class


!

Initializer Lists
Contact::Contact(char * newName, char *newAddress):Name(newName) { theAddress = new char[strlen(newAddress)+1]; strcpy(theAddress, newAddress); } The Name(char *) constructor is called instead of the default one with newName as argument Name::Name(char * newName) { theName = new char[strlen(newName)+1]; strcpy(theName, newName); }

What if a non-default constructor of base class is to be called? Contact c( Tarek Abdelrahman , 123 Main St ); 0 T char * theName char * theAddress 1 a r e n n \0 How to call this constructor??

Name( Tarek Abdelrahman );

0 1

1 2 3 M t

n \0

Contact(..., 123 Main St ); Using initializer lists


ECE 244 Programming Fundamentals 15 Copyright 2005-2011 Tarek S. Abdelrahman

ECE 244 Programming Fundamentals

16

Copyright 2005-2011 Tarek S. Abdelrahman

Destruction of Objects of the Derived Class


! ! !

Contact Class Destructor

The destructor of the derived class is called The destructor of the base class is called The derived object itself is deleted if (cond) { Contact c; : } OR 0 T char * theName char * theAddress 1 a Contact * p = new Contact(); : delete p; n \0 ~Name(); Contact::~Contact() { delete [] theAddress; }

0 1
17

1 2

m \0 ~Contact();

Del-allocate only the new parts in Contact; assume Name is properly destructed

c
ECE 244 Programming Fundamentals

Copyright 2005-2011 Tarek S. Abdelrahman

ECE 244 Programming Fundamentals

18

Copyright 2005-2011 Tarek S. Abdelrahman

Derived and Base Objects


!

Derived and Base Objects


!

Objects of type Derived are also of type Base e.g.: Name n; Contact c; c is of type Contact and also of type Name

Implications? Name n; Contact c; n = c; c = n;

Define Contact::operator=(Name &) if you wish this to work!

"

// n.operator=(Name &) // c.operator=(Contact &)

! !

n.operator=(c); c.operator=(n)

Objects of type Base are NOT of type Derived e.g.: Name n; Contact c;
!

!
In general, one can use a derived object anywhere a base object can be used bool foo(Name x);

n is of type Name but not of type Contact Makes sense: Derived is superset of Base
19 Copyright 2005-2011 Tarek S. Abdelrahman

flag = foo (c);

"
20 Copyright 2005-2011 Tarek S. Abdelrahman

ECE 244 Programming Fundamentals

ECE 244 Programming Fundamentals

Pointers to Derived and Base Objects


!

Pointers to Derived and Base Objects


!

Pointer to objects of type Base are also pointers to objects of type Derived e.g.: Name * name_ptr; Contact * contact_ptr = new Contact(); name_ptr = contact_ptr; contact_ptr 0 \0 char * theName char * theAddress

Pointer to objects of type Derived are NOT pointers to objects of type Base e.g.: Contact * contact_ptr; Name * name_ptr = new Name(); contact_ptr = name_ptr; name_ptr char * theName contact_ptr

Compiler Error! 0 \0

name_ptr

0 \0
!

OK; Base pointer (name_ptr) can only be used to access Base members (name_ptr->), which always exist in Derived (Contact)
21 Copyright 2005-2011 Tarek S. Abdelrahman

Problem: Derived pointer (contact_ptr) may be used to access Derived members (contact_ptr->), which do not always exist in Base (Name)
22 Copyright 2005-2011 Tarek S. Abdelrahman

ECE 244 Programming Fundamentals

ECE 244 Programming Fundamentals

Pointers to Derived and Base Objects


!

Pointers to Derived and Base Objects

Now consider the following example Name * np; Contact *cp; cp = new Contact(); cp->setNameAddress( Tarek , np = cp; np char * theName 123 Main St ); 0 T 1 a n \0 np char * theName 0 1
23

cp->print(); // which print() is invoked?

np->print(); // which print is invoked? 0 T 1 a n \0

cp

char * theAddress

1 2

m \0

cp

char * theAddress

0 1

1 2

m \0

ECE 244 Programming Fundamentals

Copyright 2005-2011 Tarek S. Abdelrahman

ECE 244 Programming Fundamentals

24

Copyright 2005-2011 Tarek S. Abdelrahman

Pointer and Method Invocation


!

Virtual Functions
Consider the following example Contact : public Name { ! }; LongContact : public Name { ! }; Name *np; Contact *cp = new Contact (); LongContact *lcp = new LongContact(); cin >> userinput; if (userinput == value1) np=cp; else np=lcp; np->print(); // Which print() method is invoked?

Type obj; : obj.fcn()

Type * ptr; : ptr->fcn()

ECE 244 Programming Fundamentals

25

Copyright 2005-2011 Tarek S. Abdelrahman

ECE 244 Programming Fundamentals

26

Copyright 2005-2011 Tarek S. Abdelrahman

Dynamic (Late) Binding


!

Dynamic Binding
!

The print() of Name is invoked because the pointer is of type Name *. The compiler determines which function to call based on the type of the pointer (static or early binding) But we want print() of Contact to be invoked since the object is really of type Contact (np->Contact::print() will not work!) The solution is to tell the compiler not to determine which function to use based on the type of the pointer, but based on the type of the object! But the object is known only at run-time Tell the compiler to generate code that inspects the object pointed to by np at run-time, determine the type of the object, and then call the appropriate print () (Dynamic or late binding)
27 Copyright 2005-2011 Tarek S. Abdelrahman

Base pointer can point to base or derived objects np char * theName char * theAddress 0 1 T a n \ 0 m \ 0

0 1 1 2

Can call inherited methods in Contact using np (they came from Name), so no problem (e.g., np->setName(!)) Cannot call new functions defined in Contact but not in Name (e.g., np->setNameAddress(..) will generate a compile time error Dynamic binding is most useful for functions with the same name in Name and Contact (e.g., print())
ECE 244 Programming Fundamentals 28 Copyright 2005-2011 Tarek S. Abdelrahman

! !

ECE 244 Programming Fundamentals

Virtual Functions
!

Virtual Functions
Consider the following example Contact : public Name { ! }; LongContact : public Name { ! }; Name *np; Contact *cp = new Contact (); LongContact *lcp = new LongContact(); cin >> userinput; if (userinput == value1) np=cp; else np=lcp; np->print(); // Which print() method is invoked?

class Name { private: char * theName; public: Name(); ~Name(); : virtual void print(); };

class Contact : public Name { private: char * theAddress; public: Contact(); ~Contact(); : virtual void print(); };

ECE 244 Programming Fundamentals

29

Copyright 2005-2011 Tarek S. Abdelrahman

ECE 244 Programming Fundamentals

30

Copyright 2005-2011 Tarek S. Abdelrahman

Virtual Functions
!

Virtual Functions
class Name { private: char * theName; public: Name(); virtual ~Name(); : virtual void print(); }; class Contact : public Name { private: char * theAddress; public: Contact(); virtual ~Contact(); : virtual void print(); };

Consider the following example Contact : public Name { ! }; LongContact : public Name { ! }; Name *np; Contact *cp = new Contact (); LongContact *lcp = new LongContact(); cin >> userinput; if (userinput == value1) np=cp; else np=lcp; delete np;

ECE 244 Programming Fundamentals

31

Copyright 2005-2011 Tarek S. Abdelrahman

ECE 244 Programming Fundamentals

32

Copyright 2005-2011 Tarek S. Abdelrahman

Vous aimerez peut-être aussi