Download presentation
Presentation is loading. Please wait.
Published byJane Caldwell Modified over 6 years ago
1
Inheritance in C++ How to do it Copyright © 1998-2016 Curt Hill
Multiple Inheritance was removed Copyright © Curt Hill
2
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 © Curt Hill
3
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 © Curt Hill
4
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 © Curt Hill
5
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 © Curt Hill
6
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 © Curt Hill
7
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 © Curt Hill
8
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 © Curt Hill
9
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 © Curt Hill
10
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 © Curt Hill
11
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 © Curt Hill
12
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 © Curt Hill
13
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 © Curt Hill
14
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 © Curt Hill
15
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 © Curt Hill
16
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 © Curt Hill
17
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 © Curt Hill
18
Example Hierarchy person name employee student wage hours grad degree
Copyright © Curt Hill
19
Storage of Grad Name Person properties Hours Student properties Degree
Grad properties The IBM 360 Floating Point Trick Copyright © Curt Hill
20
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 © Curt Hill
21
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 © Curt Hill
22
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 © Curt Hill
23
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 © Curt Hill
24
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 © Curt Hill
25
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 © Curt Hill
26
Problem example Suppose: class person { protected: date birth; char name[20]; … Date is a class It must have a default constructor Copyright © Curt Hill
27
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 © Curt Hill
28
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 © Curt Hill
29
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 © Curt Hill
30
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 © Curt Hill
31
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 © Curt Hill
32
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 © Curt Hill
33
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 © Curt Hill
34
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 © Curt Hill
35
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 © Curt Hill
36
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 © Curt Hill
37
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 © Curt Hill
38
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 © Curt Hill
39
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 © Curt Hill
40
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 © Curt Hill
41
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 © Curt Hill
42
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 © Curt Hill
43
New Visibilities Derivation type / Base class visibility / Result visibility
Was Public Was Protected Was Private Public Protected Private private Copyright © Curt Hill
44
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 © Curt Hill
45
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 © Curt Hill
46
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 © Curt Hill
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.