Académique Documents
Professionnel Documents
Culture Documents
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(); };
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
n \0
:
Contact 0 1 n \0
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
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
What is Inherited?
!
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
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
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 function members (private and public) e.g.: Contact adds setNameAddress and print()
Functions in Contact override functions with the same name (signature) in Name
11
12
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
13
14
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??
0 1
1 2 3 M t
n \0
16
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
18
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
"
! !
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
"
20 Copyright 2005-2011 Tarek S. Abdelrahman
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
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
char * theAddress
1 2
m \0
cp
char * theAddress
0 1
1 2
m \0
24
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?
25
26
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
! !
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(); };
29
30
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;
31
32