Inheritance in C++ How to do it Copyright © 1998-2016 Curt Hill Multiple Inheritance was removed Copyright © 1998-2016 Curt Hill
Very little new Syntax In the header In the class code Ancestral class Specify the type of derivation Give the new properties and methods Virtual methods In the class code Constructors Ancestral method calls How used in client code Copyright © 1998-2016 Curt Hill
Terminology Derive Ancestor Method Property To make a new class which inherits properties and methods from an older class Ancestor The older class which defines the inherited properties and methods Also known as the base class or super class Method Member function Property Member data Copyright © 1998-2016 Curt Hill
Declaring a derived class Normal class syntax is: class name { Name is the name of the new class Derivation syntax: class name : [visibility] ancestor { Name is the new class name Ancestor is the ancestral class name Visibility is one of the three visibilities Public is usually best, default is private Copyright © 1998-2016 Curt Hill
Notes The ancestral class must be accessible via an include It may also be a derived class The visibility type is most frequently public Other visibilities will be considered later Copyright © 1998-2016 Curt Hill
Example: Person class person { private: gender_type gender; protected: wxString name; date birth; public: person (); person (wxString nme, gender_type m_or_f, const date& d); bool is_male() const; bool set_gender(char m_or_f); virtual wxString ToString() const; }; // end of class person Copyright © 1998-2016 Curt Hill
Commentary Except for protected and virtual there was nothing new about this class An inheritance hierarchy may be rooted by any class Now here is the student Copyright © 1998-2016 Curt Hill
Example: Student class student: public person { protected: int hours; college_type college; public: student (); student (char nme[], char m_or_f, date& d,int h=0, char c = 'u'); void set_college(char c); void incr_hours(int h); virtual void ToString(char *)const; }; // student class Copyright © 1998-2016 Curt Hill
Notes Every property and method of person now exists in student The visibility is not changed Protected and public properties and methods may be accessed by student code Copyright © 1998-2016 Curt Hill
Adding properties and methods Protected is only of importance in derivations Allows a derived class to access but not client Any methods given may either be new or override an existing method They augment existing methods Properties add to existing properties The virtual is optional in all but the base class Good documentation Copyright © 1998-2016 Curt Hill
Override To override is to create a new method with the same signature as an inherited method The override method will be executed and not the overridden Regardless of where the call occurs Copyright © 1998-2016 Curt Hill
Removing There is no remove syntax There are tricks Restricted derivations reduce everything of a visibility to a lower visibility Most properties are hidden from client so that is not a problem Methods: Change the visibility from public to protected or private Now inaccessible Override to do nothing or error Copyright © 1998-2016 Curt Hill
Polymorphism Objects in the same inheritance tree are interchangable Any may be called Choosing the correct function based on the object at run-time Dynamic binding Only possible with pointers Pointer type must be an ancestral type Copyright © 1998-2016 Curt Hill
Binding Earlier programming languages used static binding only At compile or link time determine the function needed Examples: Pascal, C, COBOL Some programming languages use dynamic binding only Determine function needed at run time Examples: LISP and Java C++ uses both, depending on situation Copyright © 1998-2016 Curt Hill
C++ Binding Stroustrup was walking a fine line in the design of C++ He wanted the efficiency of C and the OO power of Smalltalk Thus he puts in the hands of the programmer whether the method is polymorphic, that is has dynamic binding This is done with presence of virtual keyword Copyright © 1998-2016 Curt Hill
Interchangeability Polymorphism makes types interchangeable These classes have an “is a” relationship A cast converts a value from one type to another Interchangeability means to accept that value without cast or other change Upcasting is an example Copyright © 1998-2016 Curt Hill
Upcasting To upcast is to treat an object lower on the inheritance tree as if it were higher To treat a derived class like one of its super classes It is easy – not actually a cast at all The storage of the ancestor always precedes that of the descendent See the pictures in next two slides Copyright © 1998-2016 Curt Hill
Example Hierarchy person name employee student wage hours grad degree Copyright © 1998-2016 Curt Hill
Storage of Grad Name Person properties Hours Student properties Degree Grad properties The IBM 360 Floating Point Trick Copyright © 1998-2016 Curt Hill
C++ Requirements for Polymorphism The object must be referenced by a pointer Pointers are always same length The pointer type must be a pointer to the base type The function called must be declared virtual in the base type All the sub-classes have the function with the same signature Copyright © 1998-2016 Curt Hill
Polymorphism Is enabled by Virtual functions Any ancestral method that is prefixed by virtual forces all descendent functions with same signature to also be virtual The polymorphism is only demonstrated when a pointer is used. Pointer must be to ancestral class Stack items are of different sizes so are not interchangeable Unlike pointers Copyright © 1998-2016 Curt Hill
Polymorphic Non-Example Student s, * sptr; Person p, *pptr; st = s.ToString(); This is not polymorphic since we know exactly what the type of s is. sptr->set_name(“Bill Smith”); This is not polymorphic since set_name is only defined in Person Copyright © 1998-2016 Curt Hill
Polymorphic Example Person * p; p = new student(…); p = new person(…); // Assignment of any // descendent is legal st = p->ToString(); This is polymorphic since we do not know whether p is a pointer to a person or any of its descendents Run-time system must figure it out for us Copyright © 1998-2016 Curt Hill
Consider class X { void A(){ … B(); …} virtual void B() {…} }; // end of X class Y:public X { virtual void B() {…} }; // end of Y X * u; Y * v; u->A(); // Calls X.A and then X.B v->A(); // Calls X.A and then Y.B A descendent B is called by an ancestral A Copyright © 1998-2016 Curt Hill
Constructors The idea is that we build the class values when it is created There are two related problems having to do with default constructors Constructing a derived class must also construct the ancestral When the constructor starts any contained classes are already made Copyright © 1998-2016 Curt Hill
Problem example Suppose: class person { protected: date birth; char name[20]; … Date is a class It must have a default constructor Copyright © 1998-2016 Curt Hill
The Person Constructor Person::person(…){ birth = date(1,2,87); When the constructor starts (following the {) All the contained or ancestral things have already been constructed Two problems: Default constructor may not be accessible Wasteful - Default construction plus second construction Copyright © 1998-2016 Curt Hill
The solution A different notation for construction Person::person(int m,int d, int y): birth(m,d,y),name(“Bill Smith”){} Property names are treated like functions and initial value is put in them Even if not a class name These are executed before any property construction and before anything in braces Copyright © 1998-2016 Curt Hill
Same notation for inheritance In inheritance the ancestral class name is treated like a variable Thus a non-default constructor may be called Most things in the initialization list are member data names except the ancestral class Example follows Copyright © 1998-2016 Curt Hill
Example: Student constructor student::student(char nme[], char m_or_f, date & d, int h,char c) : person(nme,m_or_f,d), hours(h) { set_college(c); } Copyright © 1998-2016 Curt Hill
Summary for Construction In inheritance the ancestral class name is treated like a variable Thus a non-default constructor may be called All variable names are treated like functions Initialization list is completed before the body of the constructor is executed Often the body is empty Copyright © 1998-2016 Curt Hill
Pure Virtual Functions Used to define interface No implementation The header is assigned zero: virtual int s1(int i)const=0; virtual int s2()=0; Copyright © 1998-2016 Curt Hill
Abstract Base Classes Contain one or more pure virtual functions Either their own or inherited from a super class Cannot be instantiated Any descendent must implement all pure virtual functions to be instantiable May have a pointer of that type, which is used for polymorphism for the whole tree May not implement = operator Copyright © 1998-2016 Curt Hill
Example class shape { double x,y; public: virtual void move(double dx, double dy); virtual void draw() = 0; … }; class circle: public shape{ void draw(); … }; … shape * sp; Copyright © 1998-2016 Curt Hill
Example explained Shape is an abstract class Circle’s draw overrides shape’s draw Circle may be instantiated Even though shape cannot be instantiated a pointer that will contain several shapes may have that type Copyright © 1998-2016 Curt Hill
Accessing Overridden Methods When a descendent overrides an existing method the method is still available The ancestral name and scope resolution operator are used Consider following example Copyright © 1998-2016 Curt Hill
Example 1 class anc{ ... int meth(int a); }; // end of anc class desc: public anc{ int meth(int a); }; // end of desc int desc::meth(int a){ c = anc::meth(a); ... } Copyright © 1998-2016 Curt Hill
Example 2 Consider the ToString of the Student class It should not re-implement the ToString of Person It should just call it Such as: String student::ToString(){ String s = Person::ToString(); s += “ “ + hours; … C++ Builder or Visual Studio Copyright © 1998-2016 Curt Hill
Example 2 Consider the ToString of the Student class It should not re-implement the ToString of Person It should just call it Such as: wxString student::ToString(){ wxString s = Person::ToString(); s = s << “ “ << hours; … DevC++ Copyright © 1998-2016 Curt Hill
Visibility Again There are two ways to modify visibilities of the base class Individual methods may be altered by overriding them Override at a different visibility Can be done if base class made something other than private All visibilities may be lowered by using derivation visibility Copyright © 1998-2016 Curt Hill
Example class anc{ protected: int meth1(int a); int meth2(int a); }; // end of anc class desc: public anc{ private: int meth1(int a); public: int meth2(int a); }; // end of desc Copyright © 1998-2016 Curt Hill
Derivation Visibility The visibility given in the class header determines the visibility of the items from the superclass in this class This can reduce visibility but never make it more visible Public derivations preserve the existing visibilities Copyright © 1998-2016 Curt Hill
New Visibilities Derivation type / Base class visibility / Result visibility Was Public Was Protected Was Private Public Protected Private private Copyright © 1998-2016 Curt Hill
Other Derivations Protected visibility Private visibility Hides all methods and properties from clients Preserves access to this and sub classes Private visibility Hides all methods and properties from clients and sub classes Similar to composition where ancestral class is now private Copyright © 1998-2016 Curt Hill
Derivation Visibilities Protected and private derivation violates the notion of “is a” The derived class is no longer fully compatible because the ancestral public classes are no longer public This does not mean they are not useful Still the rule of thumb for derivation visibility is to use public unless there is a good reason Copyright © 1998-2016 Curt Hill
Conclusion Inheritance is a powerful mechanism for reusing code Function parameters allow us to unite two similar pieces of code into one Inheritance works somewhat similarly by giving new functionality without altering the ancestral class or classes Moreover it is easy There was a period when it was overused Copyright © 1998-2016 Curt Hill