Inheritance. Recall the plant that we defined earlier… class Plant { public: Plant( double theHeight ) : hasLeaves( true ), height (theHeight) { } Plant(

Slides:



Advertisements
Similar presentations
June 1, 2000 Object Oriented Programming in Java (95-707) Java Language Basics 1 Lecture 6 Object Oriented Programming in Java Language Basics Objects.
Advertisements

Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.
12/08/08MET CS Fall Polymorphism 10. Polymorphism Goal: Goal: Create methods that can be invoked with all object types, base as well as.
PolymorphismCS-2303, C-Term Polymorphism Hugh C. Lauer Adjunct Professor (Slides include materials from The C Programming Language, 2 nd edition,
Classes. Class expanded concept of a data structure: instead of holding only data, it can hold both data and functions. An object is an instantiation.
Virtual Functions Junaed Sattar November 10, 2008 Lecture 10.
Shallow Versus Deep Copy and Pointers Shallow copy: when two or more pointers of the same types point to the same memory – They point to the same data.
OOP Languages: Java vs C++
Inheritance. Types of Inheritance Implementation inheritance means that a type derives from a base type, taking all the base type’s member fields and.
Programming Languages and Paradigms Object-Oriented Programming.
Chapter 4 Inheritance Bernard Chen Spring Objective IS-A relationships and the allowable changes for derived classes The concept of polymorphism.
 2006 Pearson Education, Inc. All rights reserved Classes: A Deeper Look.
1 CISC181 Introduction to Computer Science Dr. McCoy Lecture 19 Clicker Questions November 3, 2009.
C++ Programming: Program Design Including Data Structures, Fourth Edition Chapter 13: Pointers, Classes, Virtual Functions, and Abstract Classes.
C++ Object Oriented 1. Class and Object The main purpose of C++ programming is to add object orientation to the C programming language and classes are.
Pointer Data Type and Pointer Variables
Inheritance in C++ CS-1030 Dr. Mark L. Hornick.
Chapter 15 – Inheritance, Virtual Functions, and Polymorphism
C++ Programming: From Problem Analysis to Program Design, Fourth Edition Chapter 14: Pointers, Classes, Virtual Functions, and Abstract Classes.
CSE 332: C++ templates This Week C++ Templates –Another form of polymorphism (interface based) –Let you plug different types into reusable code Assigned.
Inheritance Joe Meehean. Object Oriented Programming Objects state (data) behavior (methods) identity (allocation of memory) Class objects definition.
Chapter 9 Defining New Types. Objectives Explore the use of member functions when creating a struct. Introduce some of the concepts behind object-oriented.
Inheritance in Classes tMyn1 Inheritance in Classes We have used the Box class to describe a rectangular box – our definition of a Box object consisted.
Nirmalya Roy School of Electrical Engineering and Computer Science Washington State University Cpt S 122 – Data Structures Classes: A Deeper Look Part.
1 Inheritance We are modeling the operation of a transportation company that uses trains and trucks to transfer goods. A suitable class hierarchy for the.
Programming Languages and Paradigms Object-Oriented Programming (Part II)
CSCI-383 Object-Oriented Programming & Design Lecture 14.
Defining New Types Lecture 21 Hartmut Kaiser
Lecture 21 Multiple Inheritance. What is Multiple Inheritance? We defined inheritance earlier in the semester as a relationship between classes. If class.
Chapter 13. Procedural programming vs OOP  Procedural programming focuses on accomplishing tasks (“verbs” are important).  Object-oriented programming.
1 Inheritance. 2 Why use inheritance?  The most important aspect of inheritance is that it expresses a relationship between the new class and the base.
Chapter 12: Pointers, Classes, Virtual Functions, and Abstract Classes.
More on Drawable Objects, Hierarchical Objects Glenn G. Chappell U. of Alaska Fairbanks CS 481/681 Lecture Notes Wednesday, January.
Classes In C++ 1. What is a class Can make a new type in C++ by declaring a class. A class is an expanded concept of a data structure: instead of holding.
Copyright 2006 Oxford Consulting, Ltd1 February Polymorphism Polymorphism Polymorphism is a major strength of an object centered paradigm Same.
Programming in Java CSCI-2220 Object Oriented Programming.
C# Classes and Inheritance CNS 3260 C#.NET Software Development.
Lecture 3 Classes, Structs, Enums Passing by reference and value Arrays.
Copyright © 2012 Pearson Education, Inc. Chapter 15: Inheritance, Polymorphism, and Virtual Functions.
CPSC 252 The Big Three Page 1 The “Big Three” Every class that has data members pointing to dynamically allocated memory must implement these three methods:
Copyright © 2006 Pearson Addison-Wesley. All rights reserved Learning Objectives  Inheritance  Virtual Function.
CS-1030 Dr. Mark L. Hornick 1 Basic C++ State the difference between a function/class declaration and a function/class definition. Explain the purpose.
Effective C++, 2nd Ed. By Scott Myers. Constructors, Destructors, and Assignment Operators 11.Define a copy constructor and an assignment operator for.
C++ Inheritance Data Structures & OO Development I 1 Computer Science Dept Va Tech June 2007 © McQuain Generalization versus Abstraction Abstraction:simplify.
Copyright © 2008 Pearson Addison-Wesley. All rights reserved. Chapter 15 Inheritance.
Csi2172 class 5 Midterm: June 12. constructor Special method used to create objects of the class Never has a return type. Is called automatically upon.
 In the java programming language, a keyword is one of 50 reserved words which have a predefined meaning in the language; because of this,
CS 106 Introduction to Computer Science I 04 / 18 / 2008 Instructor: Michael Eckmann.
Inheritance Initialization & Destruction of Derived Objects Protected Members Non-public Inheritance Virtual Function Implementation Virtual Destructors.
1 Becoming More Effective with C++ … Day Two Stanley B. Lippman
Fall 2015CISC/CMPE320 - Prof. McLeod1 CISC/CMPE320 Assignment 3 is due Sunday, the 8 th at 7pm. Problems with assn 3? Discuss at your team meeting tonight.
Presented by Ted Higgins, SQL Server DBA An Introduction to Object – Oriented Programming.
Dynamic Memory Review l what is static, automatic, dynamic variables? Why are dynamic(ally allocated) variables needed l what is program stack? Function.
1 C# - Inheritance and Polymorphism. 2 1.Inheritance 2.Implementing Inheritance in C# 3.Constructor calls in Inheritance 4.Protected Access Modifier 5.The.
Chapter 7 Constructors and Other Tools Copyright © 2010 Pearson Addison-Wesley. All rights reserved.
Recap Introduction to Inheritance Inheritance in C++ IS-A Relationship Polymorphism in Inheritance Classes in Inheritance Visibility Rules Constructor.
Object Oriented Programming Elhanan Borenstein Lecture #7.
Terms and Rules II Professor Evan Korth New York University (All rights reserved)
Class Inheritance Inheritance as an is-a relationship Public derive one class from another Protected access Initializer lists in constructor Upcasting.
Chapter 12: Pointers, Classes, Virtual Functions, Abstract Classes, and Lists.
Copyright © 2002 Pearson Education, Inc. Slide 1.
Copyright © 2002 Pearson Education, Inc. Slide 1.
Abstract classes only used as base class from which other classes can be inherit cannot be used to instantiate any objects are incomplete Classes that.
Copyright © Jim Fawcett Spring 2017
CS 215 Final Review Ismail abumuhfouz Fall 2014.
Chapter 13: Pointers, Classes, Virtual Functions, and Abstract Classes
Andy Wang Object Oriented Programming in C++ COP 3330
Polymorphism Professor Hugh C. Lauer CS-2303, System Programming Concepts (Slides include materials from The C Programming Language, 2nd edition, by Kernighan.
四時讀書樂 (春) ~ 翁森 山光照檻水繞廊,舞雩歸詠春風香。 好鳥枝頭亦朋友,落花水面皆文章。 蹉跎莫遣韶光老,人生唯有讀書好。
C++ Object Oriented 1.
Presentation transcript:

Inheritance

Recall the plant that we defined earlier… class Plant { public: Plant( double theHeight ) : hasLeaves( true ), height (theHeight) { } Plant( bool withLeaves=true, double theHeight = 1) : hasLeaves( withLeaves ), height (theHeight) { } void Grow(double growBy = 1) { height += growBy ; } private: bool hasLeaves; double height; };

Suppose we need to define special plant – a flower A flower plant can grow and may or may not have leaves, just like a regular plant But it has additional properties – number of flowers and whether they are open or not We can define the new class FlowerPlant by copying and modifying the definition of Plant. Very bad practice !!! Is there a better way?

FlowerPlant is a Plant We can define FlowerPlant as inheriting from Plant We say that FlowerPlant is a (kind of) Plant This means that FlowerPlant can do everything a Plant can do, and possibly more Note the difference between “is a” relationship (FlowerPlant-Plant) and “has a” relationship (FlowerClock-Plant)

FlowerPlant defined class FlowerPlant: public Plant { public: FlowerPlant( bool flowersOpen = true, size_t numFlowers = 1, double theHeight = 1) : Plant(true, theHeight), _flowersOpen( flowersOpen ), _numFlowers (numFlowers) { } size_t GetNumFlowers() const { return _numFlowers; } void OpenFlowers() { _flowersOpen = true; } void CloseFlowers() { _flowersOpen = false; } bool IsFlowering() const { return _flowersOpen; } private: bool _flowersOpen; size_t _numFlowers; }; All right, what’s going on here? Now we can do: FlowerPlant roseBush(false, 5, 10); roseBush.Grow(10); roseBush.OpenFlowers();

Constructing FlowerPlant Each FlowerPlant object (such as roseBush in the above example) has a “Plant” part inside it: When we called Grow in the example, we talked to the “Plant” part of FlowerPlant roseBush Plant fields Plant interface Flower Plant fields Flower Plant interface When a FlowerPlant is created, the “ Plant ” part must be initialized first (before the FlowerPlant part) How? A constructor of Plant must be called in the initialization line If we don’t do it – the compiler tries to call the default constructor of Plant Good practice: always write this call explicitly

Destructing FlowerPlant What happens when roseBush goes out of scope? The destructor of FlowerPlant is called Since we didn’t define one, the compiler created it automatically – as: ~FlowerPlant() {} Does it do anything? Yes, it does!

Destructing FlowerPlant A destructor always does the following: 1. Executes the code in its scope, i.e. in { } 2. Automatically calls the destructors of the fields defined in this class 3. Automatically calls the destructor of the base class Two common mistakes with destructors: Never call a destructor explicitly! Never handle base class fields in the inheriting class destructor – let the base class destructor take care of that

Assigning/copying plants Is this legal? And what will it do? Plant otherPlant(false); FlowerPlant roseBush(false, 5, 10); 1)roseBush = otherPlant; 2)otherPlant = roseBush; Recall that the compiler automatically created operator= and copy constructor for Plant and FlowerPlant The first line does not compile – there is no assignment operator for FlowerPlant from Plant The second line works, and copies only the Plant part of roseBush “slicing” – cutting parts off the object to fit the copy target, when passed by value as a base class object

Assigning/copying plants cont. Is this legal? And what will it do? void TakeGoodCare(Plant p) {…} FlowerPlant roseBush(false, 5, 10); TakeGoodCare(roseBush); When TakeGoodCare is called, a local copy of roseBush is created The copy is of type Plant – again, slicing occurs! (this time, using a copy constructor of Plant) We probably intended the function to be void TakeGoodCare(Plant& p) {…} And then there is no copy and no slicing – function operates on the given object directly

Assigning/copying plants cont. Is this legal? And what will it do? Plant myPlants[5]; FlowerPlant roseBush(false, 5, 10); myPlants[0] = roseBush; Slicing again – by definition, an array of Plants holds only Plants What if we need a mixed array of simple Plants and FlowerPlants?

Mixing Plants with Flowers We have to use an array of pointers to Plant and dynamic allocation: Plant* myPlants[5]; myPlants[0] = new FlowerPlant(roseBush); myPlants[1] = new Plant(); And then the following code works as expected (assuming all elements are initialized as above): for (size_t i=0; i<5; i++) { myPlants[i]->Grow(3.14); }

Upgrading FlowerPlant We want to add functionality to the Grow function of FlowerPlant We want it to increase the number of flowers as well as the height We define (in FlowerPlant): void Grow(double growBy = 1) { height += growBy ; _numFlowers += size_t(growBy) ; } And it doesn’t compile  height is private to Plant - what to do?

Upgrading FlowerPlant There are two options One is to call the public function Grow of Plant: void Grow(double growBy = 1) { Plant::Grow(growBy) ; _numFlowers += size_t(growBy) ; } By defining a new Grow in FlowerPlant we hide the Grow in Plant Note that we need to specify the base class in the call – otherwise it would be an infinite recursion!

Upgrading FlowerPlant The other is to keep the Grow function as: void Grow(double growBy = 1){ height += growBy ; _numFlowers += size_t(growBy) ; } And define height as protected instead of private protected members are accessible only to this class and inheriting classes Which solution is better?

Upgrading FlowerPlant Now the following works as expected: FlowerPlant roseBush(false, 5, 10); roseBush.Grow(10); What about: Plant* myPlants[5]; myPlants[0] = new FlowerPlant(roseBush); myPlants[1] = new Plant(); myPlants[0]->Grow(); myPlants[1]->Grow(); In both lines, Grow of Plant is called We need a way to select the function to call according to the actual type of the object, and not the compile- time type of the pointer!

Upgrading FlowerPlant properly If we want the code to call the correct implementation of Grow, according to the run-time type of the object: Plant::Grow if it is a Plant and FlowerPlant::Grow if it is a FlowerPlant, Grow need to be defined as virtual in Plant: class Plant { public: … virtual void Grow(double growBy = 1) { height += growBy ; } … };

Upgrading FlowerPlant properly If a function is declared as virtual in the base class (Plant), it will automatically be virtual in the derived classes (FlowerPlant) as well – no changes necessary Yet, it is a good practice to write “virtual” when overriding as well – the code is more readable: class FlowerPlant: public Plant { public: … virtual void Grow(double growBy = 1) { Plant::Grow(growBy) ; _numFlowers += size_t(growBy) ; } … };

Upgrading FlowerPlant properly Now the following works as expected too: Plant* myPlants[5]; myPlants[0] = new FlowerPlant(roseBush); myPlants[1] = new Plant(); myPlants[0]->Grow(); myPlants[1]->Grow(); In line 5, Grow of Plant is called In line 4, Grow of FlowerPlant is called In both cases, the code looks at the object at run-time and calls the appropriate implementation for the object Note that the call still has to be legal at compile time – only functions that are declared in Plant can be called via pointer to Plant Only the implementation is selected at run-time

Generalizing further Suppose that we want to maintain a garden It may contain Plants (in particular, FlowerPlants), Butterflies, and even Squirrels We want to keep them all in a single vector We want to be able to handle the life cycle of all living things in our garden in the same way: To tell them to grow periodically To check if they are dead 

Generalizing further We define a base class LivingThing with abilities Grow and IsAlive Plants (in particular, FlowerPlants ), Butterflies, and Squirrels will inherit from it Our data structure is a vector of pointers to LivingThings: std::vector garden; Now we can write (for example): for (std::vector ::iterator cit = garden.begin(); cit != garden.end(); cit++) { (*cit)->Grow(1); // age by a month if (! (*cit)->IsAlive()) { // do cleanup }

Generalizing further But how do we define the base class LivingThing? It has to declare the functions Grow and IsAlive But it cannot implement them – there is no meaningful implementation common to all living things! We declare the functions as pure virtual: class LivingThing { public: virtual void Grow(double growBy = 1) = 0; virtual bool IsAlive() const = 0; };

Generalizing further The pure virtual functions make the LivingThing class abstract – there can be no objects which actual class is LivingThing, it’s just a common way to look at objects of derived classes. The opposite of abstract is concrete – a concrete class is one that can be instantiated In order to be concrete, derived classes need to override Grow and IsAlive with appropriate implementations A pure virtual function is a placeholder – it defines the common interface without actually implementing it The implementation will be given by inheriting classes

Generalizing further - Plant class Plant : public LivingThing { public: Plant( double theHeight ) : hasLeaves( true ), height (theHeight) { } Plant(bool withLeaves=true,double theHeight = 1): hasLeaves( withLeaves ), height (theHeight) { } virtual void Grow(double growBy = 1) { height += growBy ; } virtual bool IsAlive() const { return true;} private: bool hasLeaves; double height; }; Note that we don’t need to change anything in FlowerPlant!