Presentation is loading. Please wait.

Presentation is loading. Please wait.

C++ Programming Inheritance

Similar presentations


Presentation on theme: "C++ Programming Inheritance"— Presentation transcript:

1 C++ Programming Inheritance
Design Example classes Virtual functions Pure virtual functions Abstract classes

2 Polymorphism ... A class (A) can inherit the state (variables) and behaviour (methods) of another class (B) The relationship "Is a" ( "Inherits from") We say class A is a base class (or a generalization, or a super-type) of class B and class B is a class derived from Class A (or a specialization, or a subtype) For example, leptons, hadrons, bosons are all particles, but belong to different groups, each with their special properties Particle Lepton Hadron Boson

3 ... Polymorphism Derived classes share the same states and the same methods, but they can add their own data members and/or methods Eg. depending on the particle subtype, they may have 2 quarks or 3 quarks Derived classes may also redefine the method inherited from its super-class and provide their specialized implementation Eg. Bethe-Bloch formula is not suitable for calculating DeDx for electrons, we may need to redefine CalculateDeDx() Polymorphism An ability to create an object that has more than one form The objects belonging to different types can respond to method, field, or property calls of the same name, each one according to an appropriate type-specific behavior. The programmer (and the program) does not have to know the exact type of the object in advance, and so the exact behavior is determined at run-time (this is called late binding or dynamic binding). When processing a particle of electron type, its special implementation of CalculateDeDx() will be called

4 Example To demonstrate the design and implementation of the inheritence we will develop classes that describe typical family pets Let's try to find common characteristics typical of our pets - cats and dogs Each one has a name They eat - we give them food They “speak” - dogs bark, cats meow Specific behaviours: Cats hunt mice Dogs guard home

5 Design ... Dog name Eat() Speak() Cat name Eat() Speak() Pet name Eat() Speak() The common data members and functions can be regrouped in a base class Pet (The specific behaviors will be considered later) Dog Cat

6 Classes (definition) Declaration of the inheritance relationship
#include <string> class Pet { public: Pet(std::string name); void Eat(); void Speak(); std::string Name(); private: std::string m_name; }; #include “Pet.h” #include <string>  class Dog : public Pet { public: Dog(std::string name); }; Declaration of the inheritance relationship #include “Pet.h” #include <string>  class Cat : public Pet { public: Cat(std::string name); }; Pet name Eat() Speak() Dog Cat

7 Classes (implementation)
#include "Pet.h" #include <iostream> Pet::Pet(std::string name) : m_name(name) { } void Pet::Eat() { std::cout << m_name << " eats" << std::endl; void Pet::Speak() { std::cout << m_name << " speaks" << std::endl; std::string Pet::Name() { return m_name; #include "Dog.h" #include <iostream> Dog::Dog(std::string name) : Pet(name) { } #include "Cat.h" #include <iostream> Cat::Cat(std::string name) : Pet(name) { } Pet name Eat() Speak() Initialisation of the base class Dog Cat

8 Classes (use of) ... main1.cxx
#include "Dog.h" #include "Cat.h" int main() { Dog dog("Lassie"); Cat cat("Tilly"); Cat cat2("Tom"); // When you arrive at home pets welcome you dog.Speak(); cat.Speak(); cat2.Speak(); // We have to feed them dog.Eat(); cat.Eat(); cat2.Eat(); } main1.cxx Declaration of objects with their specific types (by derived classes) Calling functions defined in the base class [localhost]> ./atHome1 Lassie speaks Tilly speaks Tom speaks Lassie eats Tilly eats Tom eats

9 ... Classes (use of) main.cxx
#include "Dog.h" #include "Cat.h" #include <vector> int main() { Dog dog("Lassie"); Cat cat("Tilly"); Cat cat2("Tom"); // The collection of our pets std::vector<Pet*> ourPets; ourPets.push_back(&dog); ourPets.push_back(&cat1); ourPets.push_back(&cat2); // When you arrive at home pets welcome you std::vector<Pet*>::iterator it; for ( it=ourPets.begin(); it != ourPets.end(); it++ ) { Pet* pet = *it; pet->Speak(); } /// We have to feed them (*it)->Eat(); main.cxx The existence of the base class allows us to use our objects in generic way Using objects by their base type (Pet *) [localhost]> ./atHome Lassie speaks Tilly speaks Tom speaks Lassie eats Tilly eats Tom eats

10 Specialization of functions ...
We will make our model more precise: The Dog eats the granules ProPlan The Cat eat the cans Whiskas The Dog barks The Cat meow Modelling: Pet name Eat() Speak() Each derived class redefines the functions of the base class Dog Eat() Speak() Cat Eat() Speak()

11 ... Specialization of functions
We will add these methods to the classes Dog and Cat For the correct function to be called, it must be declared as being virtual The "correct" function = the function defined for the class whose dynamic type corresponds to the object The object defined by reference Pet1 is of Dog type, Pet2 of Cat type The virtual function acts as an interface to the functions defined in the base class and all the derived classes #include <string> class Pet { public: Pet(std::string name); virtual void Eat(); virtual void Speak(); private: std::string m_name; }; #include “Pet.h” #include <string>  class Dog : public Pet { public: Dog(std::string name); virtual void Eat(); virtual void Speak(); }; #include “Pet.h” #include <string>  class Cat : public Pet { public: Cat(std::string name); virtual void Eat(); virtual void Speak(); }; It is not obligatory to re-declare virtual functions in derived classes, but it's good practice to do so La déclaration de la relation de héritage

12 ... Specialization of functions ...
In implementing these functions, there is nothing special: Dog::Eat() { std::cout << Name() << " eats the granules ProPlan " << std::endl; } void Dog::Speak() { std::cout << Name() << ": woof, woof !! " << std::endl; Cat::Eat() { std::cout << Name() << " eats the cans Whiskas “ << std::endl; } void Cat::Speak() { std::cout << Name() << ": meow, meow !! " << std::endl;

13 ... Specialization of functions
We compiles and run the two programs again: [localhost] > ./atHome1 Lassie: woof, woof !!! Tilly: meow, meow !!! Tom: meow, meow !!! Lassie eats the granules ProPlan Tilly eats the cans Whiskas ... If objects were declared with their specific types (through derived classes) If objects were declared with their generic type (through a base class) [localhost]> ./atHome Lassie speaks Tilly speaks Tom speaks Lassie eats Tilly eats ... [localhost] > ./atHome Lassie: woof, woof !!! Tilly: meow, meow !!! Tom: meow, meow !!! Lassie eats the granules ProPlan Tilly eats the cans Whiskas ... When functions are not declared virtual, it is the function of the declared type that is called, without taking into account the actual type of object When functions are declared virtual, it is the function of the real type of object, which is called

14 If You Buy a Canary We add a new class derived from the class Pet:
#include “Pet.h” #include <string>  class Canary : public Pet { public: Canary(std::string name); }; #include "Canary.h" #include <iostream> Canary::Canary(std::string name) : Pet(name) { } The Canary class does not specify the methods of the base class main4.cxx // ... #include "Canary.h" int main() { Canary canary("Robbie"); ourPets.push_back(&canary); } [localhost]> ./atHome Lassie: woof, woof !!! Tilly: meow, meow !!! Tom: meow, meow !!! Robbie speaks Lassie eats the granules ProPlan Tilly eats the cans Whiskas Tom eats the cans Whiskas Robbie eats

15 Pure Virtual Functions ...
We are going to re-examine the requirements of our program Imagine that we leave our pets to our neighbour and ask them to replace us during our holidays Our program will help him know the needs of our pets: But what does Robbie eat ? Our base class enabled us avoid to specify the needs of our canary [localhost]> ./atHome Lassie: woof, woof !!! Tilly: meow, meow !!! Tom: meow, meow !!! Robbie speaks Lassie eats the granules ProPlan Tilly eats the cans Whiskas Tom eats the cans Whiskas Robbie eats

16 ... Pure Virtual Functions ...
The base class can require all derived classes to implement a function: To do this the function must be declared as a pure virtual function #include <string> class Pet { public: Pet(std::string name); virtual void Eat() = 0; virtual void Speak(); private: std::string m_name; }; void Pet::Eat() { std::cout << m_name << " eats" << std::endl; } The pure virtual functions have no implementation

17 ... Pure Virtual Functions
We try to compile our program ... and it does not compile! It is impossible to create an instance of the class that has not defined all inherited pure virtual functions Classes whose instance cannot be created are called abstract classes [localhost] > g++ -I. *.cxx -o atHome4 main4.cxx: In function ‘int main()’: main4.cxx:10: error: cannot allocate an object of abstract type ‘Canary’ Canary.h:4: note: because the following virtual functions are pure within ‘Canary’: Pet.h:10: note: virtual void Pet::Eat() Pet.h:11: note: virtual void Pet::Speak()

18 Specific functions ... We will consider specific behaviors:
The cat chases the mouse Dog guards house Dog name Eat() Speak() Guard() Cat name Eat() Speak() HuntMice Pet name Eat() Speak() The specific functions are added only in derived classes Dog Guard() Cat HuntMice()

19 ... Specific functions ... main1.cxx main.cxx
#include "Dog.h" #include "Cat.h" int main() { Dog dog("Lassie"); Cat cat("Tilly"); Cat cat2("Tom"); // When you arrive at home pets welcome you dog.Speak(); ... // We have to feed them dog.Eat(); // And everyone continues in their work dog.Guard(); cat.HuntMice(); } main1.cxx main.cxx #include "Dog.h" #include "Cat.h" #include <vector> int main() { ... // The collection of our pets std::vector<Pet*> ourPets; ourPets.push_back(&dog); // When you arrive at home pets welcome you // We have to feed them // And everyone continues in their work for ( it=ourPets.begin(); it != ourPets.end(); it++ ) { Pet* pet = *it; Dog* dog = dynamic_cast<Dog*>(pet); If ( dog ) dog->Guard(); Cat* cat = dynamic_cast<Cat*>(pet); If ( cat ) cat->HuntMice(); } The specific functions can not be called in a generic way

20 Conclusions The class inheritance allows us
Avoid duplication of common code By a common implementation in the base class Process objects in a generic way Collections of objects by the type of base class Call functions with the common interface By declaring virtual functions Forcing Derived classes implement the interfaces required Declaring pure virtual functions


Download ppt "C++ Programming Inheritance"

Similar presentations


Ads by Google