SlideShare a Scribd company logo
1 of 28
Download to read offline
1 
(6) C++ Abstractions 
Nico Ludwig (@ersatzteilchen)
2 
TOC 
● (6) C++ Abstractions 
– Aggregation: Whole – Part Associations 
– Inheritance: Generalization – Specialization Associations 
– Non-public Inheritance 
– Unified Modeling Language (UML) Basics 
– The Substitution Principle 
– Object Slicing and the extra Layer of Indirection 
– Polymorphism 
● Problem of Pasta-object-oriented Architecture 
● Dealing with specialized Behavior 
● Overriding and Hiding 
● The Dependency Inversion Principle 
● Souces: 
– Bjarne Stroustrup, The C++ Programming Language 
– John Lakos, Large-Scale C++ Software Design
3 
Defining the UDT Car with Classes 
● Definition of the UDT Car: 
– It has two fields: 
● theEngine 
● spareTyre 
● Car has an Engine and a SpareTyre. 
– And three member functions: 
● StartEngine() 
● SetSpareTyre() 
● GetSpareTyre() 
● The definition of this UDT shouldn't contain any surprises. 
– Therefor we're going to use it for the following discussion. 
class Car { // UDTs Engine and Tyre elided. 
Engine* theEngine; 
Tyre* spareTyre; 
public: 
void StartEngine() { 
std::cout<<"start Car"<<std::endl; 
theEngine->Start(); 
} 
void SetSpareTyre(const Tyre* spareTyre) { 
this->spareTyre = spareTyre; 
} 
const Tyre* GetSpareTyre() const { 
return spareTyre; 
} 
}; 
// Creation and usage of a Car instance: 
Car fordFocus; 
fordFocus.SetSpareTyre(new Tyre); 
fordFocus.StartEngine();
4 
Idioms of Object Orientation 
● Effectively, the combination of self contained data and behavior is our aim. 
● In sum, following idioms are required to implement this aim: 
– 1. Abstraction by combining data and functions into a type. 
– 2. Encapsulation to protect data from unwanted access and modification: 
● The day-part of a Date instance should not be modifiable from "outside". 
– 3. The whole – part (aggregation or composition) association: 
● We can say "A car object has an engine object.". 
– 4. The specialization – generalization (inheritance) association: 
● We can say "three cars drive in front of me", rather then saying that there "drives a van, a bus and a sedan in front of me". The generalization is 
possible, because e.g. a bus is a car. 
● "Object-orientation" (oo) is the umbrella term for these idioms. 
– Oo languages provide features that allow expressing these idioms. 
– Now we're going to understand specialization – generalization.
5 
UML Notation of Car with Whole-Part Associations 
● A Unified Modeling Language (UML) "class diagram" to design aggregated types. 
– A class diagram underscoring structure, emphases Car's associations: 
Car 
Car has Engine and has Tyre. The hollow 
diamond means "aggregation": the Car is "the whole", 
but Engine and Tyre are "the parts". 
This is a note. 
The class Car. 
– A class diagram underscoring contents, emphases Car's details: 
Car 
- theEngine : Engine* 
- spareTyre : Tyre* 
+ StartEngine() 
+ GetSpareTyre() : Tyre* 
+ SetSpareTyre() 
Engine 
Tyre 
Car expanded 
The fields ("attributes" in 
UML lingo) of Car. The fields 
are private, mind the "-" notation. 
The member functions ("operations" in 
UML lingo) of Car. The member functions 
are public, mind the "+" notation. 
– A Car instance aggregates an Engine instance (Not: the UDT Car aggregates the UDT Engine!) 
● UML is a language to describe oo systems. 
● The class diagram in the structural notation 
shows the associations. 
● The conciser notation shows the details of the 
types (members, their accessibility etc.). 
● The static fields and methods are represented 
with underlined texts in UML.
6 
Expressing Generalization – Specialization in C++ 
● Present UDTs can be used as base types for new types. 
– More special types inherit from more general types. This is called inheritance. 
● Instead of "inherits from" we'll occasionally use the phrases "derives from" or "extends". 
– The data (i.e. the (private) fields) of base types is inherited by the new type. 
– The behavior (i.e. the member functions) of base types is inherited by the new type. 
● The new type inherits the public interface from its base types. 
● The inheriting type can access the public interface of its base types but not their private members. 
– The new type can add more members to the inherited ones. 
– Where an object of base type was used, an object of the derived type can also be used. 
● This is called substitution principle. 
● In C++ a new type can inherit from more than one type! 
– This is called multiple inheritance (MI). We are not going to discuss multiple inheritance! 
● Let's learn how inheritance is notated in C++... 
● C++' fundamental types and enums can not be 
used as base types!
7 
Inheritance and Type Specialization in C++ 
● We've to adorn the class definition of the derived type by naming the base types. 
– Here we're going to introduce the UDT Bus being inherited from Car. 
– This inheritance expresses following specialization: a Bus is a Car. 
// Bus inherits from Car: 
class Bus : public Car { // (members hidden) 
static const int COUNT_SEATBENCHES = 42; 
int nOccupiedSeatBenches; 
public: 
bool NewPassengerCanEnter() const { 
return COUNT_SEATBENCHES <= nOccupiedSeatBenches; 
} 
}; 
● So let's instantiate and use a Bus: 
– Mind that we can call Car's inherited and Bus' new member functions on a Bus object. 
Bus bus; 
bool hasVacantSeats = bus.NewPassengerCanEnter(); // Accessing a member function of Bus. 
// Accessing a member function of Bus' base type Car: 
Tyre spareType = bus.GetSpareTyre(); // Bus inherited (almost) all members of Car. A Bus is a Car. 
– Ctors of base types are not inherited to the subtype! 
● The type Bus is derived from Car. So a Bus is a 
Car. 
● A Bus has 42 seat benches. This means that the 
count of seat benches is limited. 
● A certain count of seat benches 
(nOccupiedSeatBenches) is occupied by 
passengers. 
● Bus introduces a new public member function 
NewPassengerCanEnter(). This member function 
is not present in the base type Car. The interface 
of Bus then consists of all public members of Car 
(save Car's ctors) as well as the new public 
member function NewPassengerCanEnter(). 
● Is the type Bus allowed to access theEngine in 
Car? 
● Ctors of base types are not directly inherited to 
the subtype! But they are called on the creation of 
a new instance from the most special to the most 
general type.
8 
Sidebar: Non-public Inheritance 
● We've used public inheritance in Bus. What happens w/o the public keyword? 
// Bus inherits from Car non-publicly: 
class Bus : Car { // (members hidden) 
}; 
void StartEngine() { /* pass */ } 
// Bus inherits from Car privately: 
class Bus : private Car { // (members hidden) 
}; 
class Car { // (members hidden) 
public: 
}; 
● In this case non-private members of Car are inherited as private members into Bus: 
Car car; 
car.StartEngine(); // Ok! Call the public function Car::StartEngine(). 
Bus bus; 
bus.StartEngine(); // Invalid! The inherited function Car::StartEngine() can't be called! - It's private in Bus! 
● Non-public inheritance is used rarely. 
– It can be useful with multiple inheritance and to "encapsulate substitutability". 
● By default classes apply private inheritance and structs apply public inheritance. 
● There also exists protected inheritance. – Its 
effect can be derived form the effect of private 
inheritance. 
● "Encapsulation of substitutability" means that 
everywhere a Car was used we can no longer 
pass a Bus. – Because this "is a" relationship 
grew private as well!
9 
UML Notation of Car with the Specialization Bus 
● The UML does also allow designing specialized types in class diagrams: 
Car 
Bus 
- COUNT_SEATBENCHES : int = 42 
- nOccupiedSeatBenches : int 
+ NewPassengerCanEnter() : bool 
Bus inherits Car. The triangular hollow 
arrow-tip means "inheritance". 
The constant field "COUNT_SEATBENCHES" is 
static (it's a "classifier scope member" in UML lingo). 
static members are underscored in the UML notation. 
● In oo, aggregation and specialization associations create a type hierarchy! 
– This can be nicely shown in UML class diagrams: 
– We're going to extend this hierarchy during the following discussion. 
Engine 
Car 
Tyre 
Bus
10 
So, what is oo Programming all about? 
● The reality can be simulated to a good degree with oo-types! 
– Most real associations can be expressed with aggregation and specialization. 
– Even customers can understand, how oo-types function (UML)! 
● Thinking in type interfaces rather than in algorithms and procedures: 
– Interface and implementation can be separated, but types are complete. 
– First define all interfaces, then implement the type completely. 
● Instead of algorithms with functions, we can build architectures with UDTs. 
– Recurring UDTs architectures are called design patterns. 
– There exist simple and complex design patterns. 
● Successful (oo) programmers identify and use design patterns.
11 
Inheritance defines Substitutability 
● We discussed that, e.g., a Bus is a Car and we expressed this with inheritance. 
● Another way to understand this association: inheritance defines substitutability! 
– Wherever the UDT Car is awaited, any UDT inherited from Car can be used, e.g. Bus. 
– Because a Bus is a Car! 
● Let's understand this better with an example of substitution. 
– We'll also introduce another subtype of Car: VintageCar! 
Car 
Bus VintageCar 
Car car; 
Bus bus; 
VintageCar vintageCar; 
Car anotherCar1 = bus; // Aha! We can assign a Bus to a Car object. A Bus is a substitute for a Car. 
Car anotherCar2 = vintageCar; // We can assign a VintageCar to a Car object. A VintageCar is a 
// substitute for a Car. 
Bus anotherBus = vintageCar; // Invalid! A VintageCar is no Bus. VintageCar and Bus are 
// siblings in the inheritance hierarchy, they don't "know" each 
// other!
nOccupiedSeatBenches 
spareTyre 
nOccupiedSeatBenches 
spareTyre 
12 
Substitutability and Object Slicing 
● The substitution principle as we have used it introduces a problem: slicing. 
● When an object of derived type is assigned to an object of base type, the derived type's additional fields are sliced away! 
– The object bus contains all fields of type Bus: 
Bus bus; 
– Assigning bus to the car object slices the object's 
additional Bus-fields: 
● Substitution also works for pointer (and reference) types of inherited types. 
– But assigning a pointer to another pointer doesn't slice! 
carPointer still points to a "full" Bus object! 
● Using pointers added an extra layer of indirection, which avoids object slicing! 
bus 
theEngine 
car 
Car car = bus; // Slicing (calls the cctor). 
Bus* busPointer = &bus; 
Car* carPointer = &bus; // No slicing! 
busPointer 
(Bus) 
theEngine 
carPointer
13 
Static and dynamic Type of an Object 
● On using substitutability with pointers, an object can have a static and a dynamic type. 
– Originally we used pointers to avoid object slicing with an extra layer of indirection. 
– The pointer type of the object is the static type of the object. 
● The static type is the type of the variable. 
– The type of the object "behind the pointer" is the dynamic type of the object. 
– Hence we'll use pointers with dynamic memory allocation to make the difference clear. 
● We can cast the dynamic type "out of" the statically typed pointer. 
– Then we can access the members of the dynamic type. 
– Objects of varying dynamic type can be referenced by an object of a static type. 
Car* car = new VintageCar; // Let's point car to a VintageCar. Static type: Car*, dynamic type: VintageCar. 
VintageCar* vintageCarBehind = static_cast<VintageCar*>(car); // (1) Cast "the VintageCar out of car". 
vintageCarBehind->CrankUntilStarted(); 
Bus* busBehind = static_cast<Bus*>(car); // (2) Also ok! Cast "a Bus out of car". But it doesn't work as 
// intended as car doesn't point to a Bus, it is similar 
// to "cast contact lenses". 
– (1) This kind of casting is called "downcasting", as we cast "down the type hierarchy". 
● The dynamic type is sometimes called the "run 
time type". 
● The separation of static and dynamic type does 
also work with C++ references. 
● There are languages in which variables have no 
static type at all, e.g. Smalltalk and JavaScript. 
● (2) There is no compile time error, because car 
could really point to a Bus, because Bus is more 
special than Car, the compiler just trusts the 
programmer, downcasting is allowed as both 
types are related. So the compiler holds the cast 
to be ok, static_casts are type-checked at 
compile time. Accessing any member of 
busBehind, instead those inherited from Car, 
results in undefined behaviour.
14 
The Garage – Car Dependency 
● UDTs itself can act as base types to exploit substitutability. 
– Imagine the recently presented class Car and the new class Garage. 
– In Garages, Cars are tried to be started with Car's member function StartEngine(). 
● The UDT Garage has an association to the UDT Car. 
– In Garages it should be allowed to start all sorts of Cars. 
● Because the behavior of all Cars is the same, however, you can start the engine. 
– All Cars have the publicized member function StartEngine() in their public interface. 
● In UML we can express that "Garage has an association to the UDT Car". 
– Garage "knows" only about Car! - Nothing about subtypes of Car! 
Garage 
+ TryToStartCar(car : Car*) 
Car 
Bus VintageCar 
Engine 
Tyre 
Garage has an association w/ Car, or: 
Garage knows about Car. (not vice versa!). 
The simple arrow with a dashed line 
expresses this "directed association". 
● The term "association": Aggregation and 
inheritance are nothing but special (and also 
tighter) associations. 
● OO seems to be perfectly good to build GUIs, 
because the visual representation of GUIs can be 
directly simulated with oo UDTs and oo 
paradigms (e.g. "has"- and "is a"-associations of 
forms and controls). - In opposite to procedural or 
functional programming.
15 
Using Cars in Garages 
class Garage { // (members hidden) 
public: 
● Now let's inspect the class Garage and its member function TryToStartCar(): 
– We've just learned that the more special UDT Bus can substitute Car, so this is possible: 
● The substitutability allows us to pass more special types toTryToStartCar(). 
– But calling StartEngine() on the passed car always calls Car::StartEngine()! 
– We awaited Car::StartEngine() and Bus::StartEngine() to be called! 
– The problem: StartEngine() is called on the static type, not on the dynamic type! 
– We should analyze this effect in a more detailed manner... 
void TryToStartCar(Car* car) const { 
car->StartEngine(); 
} 
}; 
Garage 
+ TryToStartCar(car : Car*) 
Garage joesStation; 
Car* seatLeon = new Car; 
Bus* mercedesIntegro = new Bus; 
joesStation.TryToStartCar(seatLeon); // Should call Car's StartEngine(). 
joesStation.TryToStartCar(mercedesIntegro); // Should call Bus' StartEngine() inherited from Car. 
● This example shows how the "substitution 
principle" allows that the types of a function's 
arguments (dynamic types) need not to be 
exactly the types of the declared parameters 
(static types).
16 
The Problem of special Behavior 
● To make the mentioned problem visible we'll introduce the UDTVintageCar: 
– Some VintageCars can only be started with a crank (if they have no starter)! 
– Let's respect these facts in VintageCar's interface: 
class VintageCar : public Car { // (members hidden) 
public: 
bool CrankUntilStarted() { /* pass */ } 
bool HasStarter() const { /* pass */ } 
}; 
● Ok, then we're going to give our fordThinLizzie to joesStation: 
VintageCar* fordThinLizzie = new VintageCar(1909); 
joesStation.TryToStartCar(fordThinLizzie); // Oops! Calls Car's StartEngine() and this is not enough! 
// This is no compiler error, but a logical error: the fordThinLizzie can't be started in TryToStartCar()! 
– Nobody in joesStation knows how to start our fordThinLizzie! 
– They can't just turn the key and keep going! 
– The passed Car is a VintageCar (dynamic type) – this is not respected in TryToStartCar(). 
– Maybe VintageCar is so special that we have to enhance TryToStartCar()?
17 
Type Flags to the Rescue 
● We can solve the problem by the introduction of a CarType flag field: 
// An enum for CarType flags: 
enum CarType { 
CAR_TYPE, 
BUS_TYPE, 
VINTAGE_CAR_TYPE 
}; 
● Let's apply the CarType flag on our Car types: 
// Add a CarType field to the UDT Car: 
class Car { // (members hidden) 
CarType carType; // The type flag. 
public: 
CarType GetCarType() const { 
– How will this help us? => With this flag we can identify the dynamic type of a Car! 
return carType; 
} 
void SetCarType(CarType carType) { 
this->carType = carType; 
} 
}; 
// Create a Car object and flag it as being of "CAR_TYPE". 
Car* seatLeon = new Car; 
seatLeon->SetCarType(CAR_TYPE); 
// Create a VintageCar object and flag it as being of "VINTAGE_CAR_TYPE". 
Car* fordThinLizzie = new VintageCar; 
fordThinLizzie->SetCarType(VINTAGE_CAR_TYPE);
18 
Type Flags in Action 
● Now we have to modify TryToStartCar() to interpret the CarType flag: 
void Garage::TryToStartCar(Car* car) const { 
// If car's CarType flag is VINTAGE_CAR_TYPE start it in a special way: 
if (VINTAGE_CAR_TYPE == car->GetCarType()) { 
// Cast the dynamic type "out of" car: 
VintageCar* vintageCar = static_cast<VintageCar*>(car); 
// …to access VintageCar's interface: 
if (!vintageCar->HasStarter()) { 
vintageCar->CrankUntilStarted(); 
} else { 
vintageCar->StartEngine(); 
} 
// Else use the default start procedure for other cars: 
} else { 
car->StartEngine(); // Start other cars just by calling StartEngine(). 
} 
} 
● Yes, with this implementation of TryToStartCar() we can start fordThinLizzie: 
VintageCar* fordThinLizzie = new VintageCar(1909); 
fordThinLizzie->SetCarType(VINTAGE_CAR_TYPE); 
joesStation.TryToStartCar(fordThinLizzie); // Ok! TryToStartCar() will pick the correct start-algorithm 
// depending on the CarType flag!
19 
Other special Types need Handling 
● After a while the clientele at joesStation grows: 
– More and more clients bring their diesel cars to joesStation. 
– But old diesel cars can't be started in Garages! A glowing procedure is required! 
– As an oo programmer we start by encapsulating the diesel concept into a UDT: 
Car 
Bus VintageCar DieselCar 
● Btw.: Virtually our type hierarchy is becoming dubious! 
+ Glow() : bool 
– In fact we needed to redesign the hierarchy, but we're not going to do this in this here! 
Car Engine 
DieselEngine 
OttoEngine 
Bus VintageCar 
New aspects: 
1. In reality the type of fuel is encapsulated in 
the Engine! 
2. There also exist Buses and VintageCars 
using diesel fuel. 
=> We can use Engine as an extra level of 
indirection to handle these aspects.
20 
Type Flags are becoming nasty... 
● After extending the enum CarType we can modify TryToStartCar() accordingly: 
void Garage::TryToStartCar(Car* car) const { 
if (VINTAGE_CAR_TYPE == car->GetCarType()) { /* pass */ 
} else if(DIESEL_CAR_TYPE == car->GetCarType()) { 
DieselCar* dieselCar = static_cast<DieselCar*>(car); 
dieselCar->Glow(); 
dieselCar->StartEngine(); 
} else { /* pass */ } 
} 
// The CarType flag 
// DIESEL_CAR_TYPE needs 
// to be added: 
enum CarType { 
// (members hidden) 
DIESEL_CAR_TYPE 
}; 
DieselCar* dieselCar = new DieselCar(); 
fordThinLizzie->SetCarType(DIESEL_CAR_TYPE); 
joesStation.TryToStartCar(dieselCar); // Ok! TryToStartCar() will pick the correct start-algorithm! 
● This works, but should we really add more CarType flags for upcoming Car types? 
– Let's remember that we also have to add more else ifs for upcoming Car types! 
– It's uncomfortable and unprofessional doing the same all over and knowing about that! 
– This approach is also very error prone! 
● Hm... what is the basic problem we've encountered just now?
21 
A "Pasta-object-oriented" Hierarchy 
● We broke the dependency "Garage – Car" in a negative way! 
Garage 
Garage has meanwhile dependencies to 
Car, and all of Car's subtypes or: Garage knows 
about all subtypes of Car, and Garage needs to 
get acquainted to all future subtypes of Car! 
– Garage needs to know each subtype of Car now and in future! 
● We can see this, because Garage::TryToStartCar() inspects the dynamic type of the Car parameter. 
● We needed to interpret flags, because we had to deal w/ different interfaces of the dyn. type. 
● We have to make downcasts to the dynamic type respectively! 
● The bad consequence: Garage::TryToStartCar() must be modified when new Car types emerge! 
– We can also spot a "bad smell" in the class diagram! 
● There are dependencies to the base type Car and to all of its (currently known) subtypes. 
● It lead us to spaghetti programming the oo-way! How can we improve that? 
Car 
DieselCar 
VintageCar 
Bus 
● Often too many arrows pointing from a single type 
to multiple other types is a bad smell. - It can be 
nicely spotted in a UML class diagram. 
● What we've just seen on using enum type flags is 
called the "typedef-enum-antipattern".
22 
Hiding and Overriding 
● The idea is to not let Garage::TryToStartCar() select the start algorithm! 
– Instead, the start algorithm should be put into each individual Car-type! 
// Starts the Car, special implementation for VintageCars. 
void VintageCar::StartEngine() { 
std::cout<<"start VintageCar"<<std::endl; 
if (HasStarter()) { // Call the hidden StartEngine() in 
// the base class Car! 
Car::StartEngine(); 
} else { 
while (CrankUntilStarted()) { /* pass */ } 
} 
} 
// Starts the Car, special implementation for 
// DieselCars. 
void DieselCar::StartEngine() { 
std::cout<<"start DieselCar"<<std::endl; 
Glow(); // Glowing. 
// Call the hidden StartEngine() in the 
// base class Car! 
Car::StartEngine(); 
} 
void Garage::TryToStartCar(Car* car) const { 
car->StartEngine(); // Well, that's a simple implementation! The knowledge and responsibility about 
// and for the start algorithm is delegated to the dynamic type "behind" car. 
} 
● But it can't work, as we didn't override the member function Car::StartEngine()! 
joesStation.TryToStartCar(fordThinLizzie); // But... it doesn't work! 
// >start Car // Car::StartEngine() is called! 
joesStation.TryToStartCar(new DieselCar); // Doesn't work either! 
// >start Car // Car::StartEngine() is called! 
● Why do we need to call StartEngine() with a 
Car::-prefix? 
● 1. VintageCar could derive from multiple other 
base types, so one base type needs to be 
explicitly designated. 
● 2. If StartEngine() would be called in 
VintageCar::StartEngine() it lead to an infinite 
recursion, because Car::StartEngine() is hidden 
in VintageCar::StartEngine().
23 
Hands on Overriding Member Functions 
● Let's concentrate on the UDT DieselCar. 
– DieselCar can override Car's (DieselCar's base type) member function StartEngine(). 
– We've to declare overridable functions as virtual member functions in the base type: 
class Car { 
public: 
// Default implementation for Cars. 
virtual void StartEngine() { 
std::cout<<"start Car"<<std::endl; 
theEngine.Start(); // Start directly 
} 
}; 
Car 
DieselCar 
class DieselCar : public Car { 
public: 
// Special implementation for DieselCars. 
void StartEngine() { 
std::cout<<"start DieselCar"<<std::endl; 
// glowing etc. 
} 
}; 
joesStation.TryToStartCar(new DieselCar); // Works! 
// >start DieselCar // Hurray! 
– (If StartEngine() was non-virtual it would only be hidden (not overridden) in derived UDTs.) 
● Sometimes the keyword virtual is also written on 
the overriding methods (in this example it could 
be written on the method 
DieselCar::StartEngine()). It's done because of 
tradition and in order to mark that the method 
overrides another method. However, it is optional 
and it will not be checked by the compiler. - We're 
not going to repeat the virtual keyword on 
overriding methods in this course's code 
examples. 
● The virtual keyword must not be written on a non-inline 
definition.
24 
Polymorphism – chooses Implementation during Run Time 
● The inherited implementation of a member function could be inadequate! 
– Car::StartEngine() inherited by DieselCar must glow, before starting the Engine! 
● Inheriting types can override inherited implementations of member functions. 
– In C++ overridable member functions must be marked with the virtual keyword. 
● virtual member functions are often called methods in C++! 
● Overriding (late binding) is not overloading (early binding)! 
– Overriding takes effect during run time, overloading during compile time! 
– Overrides in a subtype mustn't change the signature of the overridden method. 
● Calling implementations of dynamic types on objects is called oo polymorphism. 
● The names of the parameters in an overriding 
method need no to be same as in the to-be-overridden 
method.
// Trace message instead of implementation. 
void StartEngine() { 
25 
Where is Polymorphism happening? 
● Whose implementation of method StartEngine() will be called in a Garage? ... 
? 
? 
class Garage { 
public: 
// Tries to start the passed Car. 
void TryToStartCar(Car* car) const { 
car->StartEngine(); // No downcasting! 
} 
}; 
We've the fine class hierarchy back! 
class Car { 
public: 
// Trace message instead of implementation. 
virtual void StartEngine() { 
std::cout<<"start Car"<<std::endl; 
} 
}; 
class DieselCar : public Car { 
public: 
● … it is decided during run time, depending on the dynamic type → polymorphically! 
– The implementation of TryToStartCar() needs never to be modified, if new Car types are introduced! 
– We applied the dependency inversion principle: Garage only depends on the most abstract type Car! 
std::cout<<"start DieselCar"<<std::endl; 
} 
}; 
joesStation.TryToStartCar(seatLeon); 
// >start Car 
joesStation.TryToStartCar(new DieselCar); 
// >start DieselCar 
? 
? 
Garage Car 
DieselCar VintageCar 
● Which implementation of StartEngine() will be called? 
● Car's implementation? 
● VintageCar's implementation? 
● Polymorphism: 
● In future, the implementation of the method 
StartEngine() of any other sub type of Car could be 
called! 
● In fact, the operator<< as we've overloaded it in a 
former example uses polymorphism in a similar way 
StartEngine() does: 
● As operator<<'s lhs is of type std::ostream&, it 
accepts std::cout as well std::ofstreams (so the 
substitution principle as well as static and dynamic 
types are exploited). 
● When a virtual member function is called, the dynamic 
type of the object determines, which implementation of 
that member function is really called. When a non-virtual 
member function is called, the static type of the 
object determines, which concrete implementation is 
called.
26 
When to use Inheritance? 
● Inheritance can be used to express: 
– 1. Generalization – specialization associations. 
● Bus is more special than Car, this statement justifies inheritance. 
– 2. The substitution principle and polymorphism. 
● Substitution: Whenever a Car is awaited; an object of any inherited UDT can be used. 
● Polymorphism: Methods may behave be differently in derived types. 
– 3. White-box reuse. 
● The most important usages are the substitution principle and polymorphism. 
– It comes along with generalization – specialization associations. 
– The reuse of the interface (the behavior) is the primary usage aspect! 
– White-box reuse is a secondary aspect! 
● Inheritance for reusing interfaces is the basis for most design patterns.
27 
APIE 
● The core principles of object orientation can be summarized as "A PIE": 
– (after Peter van der Linden) 
A P 
I E 
Abstraction Polymorphism 
Inheritance Encapsulation
28 
Thank you!

More Related Content

Viewers also liked

itft-Inheritance in java
itft-Inheritance in javaitft-Inheritance in java
itft-Inheritance in javaAtul Sehdev
 
Memory Management C++ (Peeling operator new() and delete())
Memory Management C++ (Peeling operator new() and delete())Memory Management C++ (Peeling operator new() and delete())
Memory Management C++ (Peeling operator new() and delete())Sameer Rathoud
 
Generalization and types
Generalization and typesGeneralization and types
Generalization and typesNaeem Hassan
 
Data Mining: Data cube computation and data generalization
Data Mining: Data cube computation and data generalizationData Mining: Data cube computation and data generalization
Data Mining: Data cube computation and data generalizationDataminingTools Inc
 
08 c++ Operator Overloading.ppt
08 c++ Operator Overloading.ppt08 c++ Operator Overloading.ppt
08 c++ Operator Overloading.pptTareq Hasan
 
Types Of Recursion in C++, Data Stuctures by DHEERAJ KATARIA
Types Of Recursion in C++, Data Stuctures by DHEERAJ KATARIATypes Of Recursion in C++, Data Stuctures by DHEERAJ KATARIA
Types Of Recursion in C++, Data Stuctures by DHEERAJ KATARIADheeraj Kataria
 
Dynamic memory allocation in c++
Dynamic memory allocation in c++Dynamic memory allocation in c++
Dynamic memory allocation in c++Tech_MX
 
Basic concepts of object oriented programming
Basic concepts of object oriented programmingBasic concepts of object oriented programming
Basic concepts of object oriented programmingSachin Sharma
 
C++: inheritance, composition, polymorphism
C++: inheritance, composition, polymorphismC++: inheritance, composition, polymorphism
C++: inheritance, composition, polymorphismJussi Pohjolainen
 

Viewers also liked (11)

itft-Inheritance in java
itft-Inheritance in javaitft-Inheritance in java
itft-Inheritance in java
 
Memory Management C++ (Peeling operator new() and delete())
Memory Management C++ (Peeling operator new() and delete())Memory Management C++ (Peeling operator new() and delete())
Memory Management C++ (Peeling operator new() and delete())
 
Generalization and types
Generalization and typesGeneralization and types
Generalization and types
 
Data Mining: Data cube computation and data generalization
Data Mining: Data cube computation and data generalizationData Mining: Data cube computation and data generalization
Data Mining: Data cube computation and data generalization
 
08 c++ Operator Overloading.ppt
08 c++ Operator Overloading.ppt08 c++ Operator Overloading.ppt
08 c++ Operator Overloading.ppt
 
Types Of Recursion in C++, Data Stuctures by DHEERAJ KATARIA
Types Of Recursion in C++, Data Stuctures by DHEERAJ KATARIATypes Of Recursion in C++, Data Stuctures by DHEERAJ KATARIA
Types Of Recursion in C++, Data Stuctures by DHEERAJ KATARIA
 
C++ classes
C++ classesC++ classes
C++ classes
 
Dynamic memory allocation in c++
Dynamic memory allocation in c++Dynamic memory allocation in c++
Dynamic memory allocation in c++
 
Basic concepts of object oriented programming
Basic concepts of object oriented programmingBasic concepts of object oriented programming
Basic concepts of object oriented programming
 
C++: inheritance, composition, polymorphism
C++: inheritance, composition, polymorphismC++: inheritance, composition, polymorphism
C++: inheritance, composition, polymorphism
 
Composition Tips
Composition TipsComposition Tips
Composition Tips
 

Similar to (6) cpp abstractions inheritance_part_i

(5) c sharp introduction_object_orientation_part_ii
(5) c sharp introduction_object_orientation_part_ii(5) c sharp introduction_object_orientation_part_ii
(5) c sharp introduction_object_orientation_part_iiNico Ludwig
 
Cble assignment powerpoint activity for moodle 1
Cble assignment powerpoint activity for moodle 1Cble assignment powerpoint activity for moodle 1
Cble assignment powerpoint activity for moodle 1LK394
 
CSCI 383 Lecture 3 and 4: Abstraction
CSCI 383 Lecture 3 and 4: AbstractionCSCI 383 Lecture 3 and 4: Abstraction
CSCI 383 Lecture 3 and 4: AbstractionJI Ruan
 
(9) cpp abstractions separated_compilation_and_binding_part_ii
(9) cpp abstractions separated_compilation_and_binding_part_ii(9) cpp abstractions separated_compilation_and_binding_part_ii
(9) cpp abstractions separated_compilation_and_binding_part_iiNico Ludwig
 
Abstract class
Abstract classAbstract class
Abstract classFraboni Ec
 
Abstract class
Abstract classAbstract class
Abstract classJames Wong
 
CSCI-383 Lecture 3-4: Abstraction
CSCI-383 Lecture 3-4: AbstractionCSCI-383 Lecture 3-4: Abstraction
CSCI-383 Lecture 3-4: AbstractionJI Ruan
 
(2) cpp abstractions abstraction_and_encapsulation
(2) cpp abstractions abstraction_and_encapsulation(2) cpp abstractions abstraction_and_encapsulation
(2) cpp abstractions abstraction_and_encapsulationNico Ludwig
 
(7) cpp abstractions inheritance_part_ii
(7) cpp abstractions inheritance_part_ii(7) cpp abstractions inheritance_part_ii
(7) cpp abstractions inheritance_part_iiNico Ludwig
 
Sealed classes java
Sealed classes   javaSealed classes   java
Sealed classes javaAryan Verma
 
(2) cpp imperative programming
(2) cpp imperative programming(2) cpp imperative programming
(2) cpp imperative programmingNico Ludwig
 
Transfer Learning _ Monk AI _ GCOEN.pptx
Transfer Learning _ Monk AI _ GCOEN.pptxTransfer Learning _ Monk AI _ GCOEN.pptx
Transfer Learning _ Monk AI _ GCOEN.pptxGDSCGCOEN
 

Similar to (6) cpp abstractions inheritance_part_i (20)

(5) c sharp introduction_object_orientation_part_ii
(5) c sharp introduction_object_orientation_part_ii(5) c sharp introduction_object_orientation_part_ii
(5) c sharp introduction_object_orientation_part_ii
 
Cble assignment powerpoint activity for moodle 1
Cble assignment powerpoint activity for moodle 1Cble assignment powerpoint activity for moodle 1
Cble assignment powerpoint activity for moodle 1
 
CSCI 383 Lecture 3 and 4: Abstraction
CSCI 383 Lecture 3 and 4: AbstractionCSCI 383 Lecture 3 and 4: Abstraction
CSCI 383 Lecture 3 and 4: Abstraction
 
(9) cpp abstractions separated_compilation_and_binding_part_ii
(9) cpp abstractions separated_compilation_and_binding_part_ii(9) cpp abstractions separated_compilation_and_binding_part_ii
(9) cpp abstractions separated_compilation_and_binding_part_ii
 
Abstract class
Abstract classAbstract class
Abstract class
 
Abstract class
Abstract classAbstract class
Abstract class
 
Abstract class
Abstract classAbstract class
Abstract class
 
Abstract class
Abstract classAbstract class
Abstract class
 
Abstract class
Abstract classAbstract class
Abstract class
 
Abstract class
Abstract classAbstract class
Abstract class
 
Abstract class
Abstract classAbstract class
Abstract class
 
O op lecture 04
O op lecture 04O op lecture 04
O op lecture 04
 
OOP lecture 04
OOP  lecture 04OOP  lecture 04
OOP lecture 04
 
OOP and C++Classes
OOP and C++ClassesOOP and C++Classes
OOP and C++Classes
 
CSCI-383 Lecture 3-4: Abstraction
CSCI-383 Lecture 3-4: AbstractionCSCI-383 Lecture 3-4: Abstraction
CSCI-383 Lecture 3-4: Abstraction
 
(2) cpp abstractions abstraction_and_encapsulation
(2) cpp abstractions abstraction_and_encapsulation(2) cpp abstractions abstraction_and_encapsulation
(2) cpp abstractions abstraction_and_encapsulation
 
(7) cpp abstractions inheritance_part_ii
(7) cpp abstractions inheritance_part_ii(7) cpp abstractions inheritance_part_ii
(7) cpp abstractions inheritance_part_ii
 
Sealed classes java
Sealed classes   javaSealed classes   java
Sealed classes java
 
(2) cpp imperative programming
(2) cpp imperative programming(2) cpp imperative programming
(2) cpp imperative programming
 
Transfer Learning _ Monk AI _ GCOEN.pptx
Transfer Learning _ Monk AI _ GCOEN.pptxTransfer Learning _ Monk AI _ GCOEN.pptx
Transfer Learning _ Monk AI _ GCOEN.pptx
 

More from Nico Ludwig

Grundkurs fuer excel_part_v
Grundkurs fuer excel_part_vGrundkurs fuer excel_part_v
Grundkurs fuer excel_part_vNico Ludwig
 
Grundkurs fuer excel_part_iv
Grundkurs fuer excel_part_ivGrundkurs fuer excel_part_iv
Grundkurs fuer excel_part_ivNico Ludwig
 
Grundkurs fuer excel_part_iii
Grundkurs fuer excel_part_iiiGrundkurs fuer excel_part_iii
Grundkurs fuer excel_part_iiiNico Ludwig
 
Grundkurs fuer excel_part_ii
Grundkurs fuer excel_part_iiGrundkurs fuer excel_part_ii
Grundkurs fuer excel_part_iiNico Ludwig
 
Grundkurs fuer excel_part_i
Grundkurs fuer excel_part_iGrundkurs fuer excel_part_i
Grundkurs fuer excel_part_iNico Ludwig
 
(1) gui history_of_interactivity
(1) gui history_of_interactivity(1) gui history_of_interactivity
(1) gui history_of_interactivityNico Ludwig
 
(1) gui history_of_interactivity
(1) gui history_of_interactivity(1) gui history_of_interactivity
(1) gui history_of_interactivityNico Ludwig
 
New c sharp4_features_part_vi
New c sharp4_features_part_viNew c sharp4_features_part_vi
New c sharp4_features_part_viNico Ludwig
 
New c sharp4_features_part_v
New c sharp4_features_part_vNew c sharp4_features_part_v
New c sharp4_features_part_vNico Ludwig
 
New c sharp4_features_part_iv
New c sharp4_features_part_ivNew c sharp4_features_part_iv
New c sharp4_features_part_ivNico Ludwig
 
New c sharp4_features_part_iii
New c sharp4_features_part_iiiNew c sharp4_features_part_iii
New c sharp4_features_part_iiiNico Ludwig
 
New c sharp4_features_part_ii
New c sharp4_features_part_iiNew c sharp4_features_part_ii
New c sharp4_features_part_iiNico Ludwig
 
New c sharp4_features_part_i
New c sharp4_features_part_iNew c sharp4_features_part_i
New c sharp4_features_part_iNico Ludwig
 
New c sharp3_features_(linq)_part_v
New c sharp3_features_(linq)_part_vNew c sharp3_features_(linq)_part_v
New c sharp3_features_(linq)_part_vNico Ludwig
 
New c sharp3_features_(linq)_part_iv
New c sharp3_features_(linq)_part_ivNew c sharp3_features_(linq)_part_iv
New c sharp3_features_(linq)_part_ivNico Ludwig
 
New c sharp3_features_(linq)_part_iv
New c sharp3_features_(linq)_part_ivNew c sharp3_features_(linq)_part_iv
New c sharp3_features_(linq)_part_ivNico Ludwig
 
New c sharp3_features_(linq)_part_iii
New c sharp3_features_(linq)_part_iiiNew c sharp3_features_(linq)_part_iii
New c sharp3_features_(linq)_part_iiiNico Ludwig
 
New c sharp3_features_(linq)_part_ii
New c sharp3_features_(linq)_part_iiNew c sharp3_features_(linq)_part_ii
New c sharp3_features_(linq)_part_iiNico Ludwig
 

More from Nico Ludwig (20)

Grundkurs fuer excel_part_v
Grundkurs fuer excel_part_vGrundkurs fuer excel_part_v
Grundkurs fuer excel_part_v
 
Grundkurs fuer excel_part_iv
Grundkurs fuer excel_part_ivGrundkurs fuer excel_part_iv
Grundkurs fuer excel_part_iv
 
Grundkurs fuer excel_part_iii
Grundkurs fuer excel_part_iiiGrundkurs fuer excel_part_iii
Grundkurs fuer excel_part_iii
 
Grundkurs fuer excel_part_ii
Grundkurs fuer excel_part_iiGrundkurs fuer excel_part_ii
Grundkurs fuer excel_part_ii
 
Grundkurs fuer excel_part_i
Grundkurs fuer excel_part_iGrundkurs fuer excel_part_i
Grundkurs fuer excel_part_i
 
(2) gui drawing
(2) gui drawing(2) gui drawing
(2) gui drawing
 
(2) gui drawing
(2) gui drawing(2) gui drawing
(2) gui drawing
 
(1) gui history_of_interactivity
(1) gui history_of_interactivity(1) gui history_of_interactivity
(1) gui history_of_interactivity
 
(1) gui history_of_interactivity
(1) gui history_of_interactivity(1) gui history_of_interactivity
(1) gui history_of_interactivity
 
New c sharp4_features_part_vi
New c sharp4_features_part_viNew c sharp4_features_part_vi
New c sharp4_features_part_vi
 
New c sharp4_features_part_v
New c sharp4_features_part_vNew c sharp4_features_part_v
New c sharp4_features_part_v
 
New c sharp4_features_part_iv
New c sharp4_features_part_ivNew c sharp4_features_part_iv
New c sharp4_features_part_iv
 
New c sharp4_features_part_iii
New c sharp4_features_part_iiiNew c sharp4_features_part_iii
New c sharp4_features_part_iii
 
New c sharp4_features_part_ii
New c sharp4_features_part_iiNew c sharp4_features_part_ii
New c sharp4_features_part_ii
 
New c sharp4_features_part_i
New c sharp4_features_part_iNew c sharp4_features_part_i
New c sharp4_features_part_i
 
New c sharp3_features_(linq)_part_v
New c sharp3_features_(linq)_part_vNew c sharp3_features_(linq)_part_v
New c sharp3_features_(linq)_part_v
 
New c sharp3_features_(linq)_part_iv
New c sharp3_features_(linq)_part_ivNew c sharp3_features_(linq)_part_iv
New c sharp3_features_(linq)_part_iv
 
New c sharp3_features_(linq)_part_iv
New c sharp3_features_(linq)_part_ivNew c sharp3_features_(linq)_part_iv
New c sharp3_features_(linq)_part_iv
 
New c sharp3_features_(linq)_part_iii
New c sharp3_features_(linq)_part_iiiNew c sharp3_features_(linq)_part_iii
New c sharp3_features_(linq)_part_iii
 
New c sharp3_features_(linq)_part_ii
New c sharp3_features_(linq)_part_iiNew c sharp3_features_(linq)_part_ii
New c sharp3_features_(linq)_part_ii
 

Recently uploaded

HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesBoston Institute of Analytics
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024SynarionITSolutions
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...apidays
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MIND CTI
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 

Recently uploaded (20)

HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 

(6) cpp abstractions inheritance_part_i

  • 1. 1 (6) C++ Abstractions Nico Ludwig (@ersatzteilchen)
  • 2. 2 TOC ● (6) C++ Abstractions – Aggregation: Whole – Part Associations – Inheritance: Generalization – Specialization Associations – Non-public Inheritance – Unified Modeling Language (UML) Basics – The Substitution Principle – Object Slicing and the extra Layer of Indirection – Polymorphism ● Problem of Pasta-object-oriented Architecture ● Dealing with specialized Behavior ● Overriding and Hiding ● The Dependency Inversion Principle ● Souces: – Bjarne Stroustrup, The C++ Programming Language – John Lakos, Large-Scale C++ Software Design
  • 3. 3 Defining the UDT Car with Classes ● Definition of the UDT Car: – It has two fields: ● theEngine ● spareTyre ● Car has an Engine and a SpareTyre. – And three member functions: ● StartEngine() ● SetSpareTyre() ● GetSpareTyre() ● The definition of this UDT shouldn't contain any surprises. – Therefor we're going to use it for the following discussion. class Car { // UDTs Engine and Tyre elided. Engine* theEngine; Tyre* spareTyre; public: void StartEngine() { std::cout<<"start Car"<<std::endl; theEngine->Start(); } void SetSpareTyre(const Tyre* spareTyre) { this->spareTyre = spareTyre; } const Tyre* GetSpareTyre() const { return spareTyre; } }; // Creation and usage of a Car instance: Car fordFocus; fordFocus.SetSpareTyre(new Tyre); fordFocus.StartEngine();
  • 4. 4 Idioms of Object Orientation ● Effectively, the combination of self contained data and behavior is our aim. ● In sum, following idioms are required to implement this aim: – 1. Abstraction by combining data and functions into a type. – 2. Encapsulation to protect data from unwanted access and modification: ● The day-part of a Date instance should not be modifiable from "outside". – 3. The whole – part (aggregation or composition) association: ● We can say "A car object has an engine object.". – 4. The specialization – generalization (inheritance) association: ● We can say "three cars drive in front of me", rather then saying that there "drives a van, a bus and a sedan in front of me". The generalization is possible, because e.g. a bus is a car. ● "Object-orientation" (oo) is the umbrella term for these idioms. – Oo languages provide features that allow expressing these idioms. – Now we're going to understand specialization – generalization.
  • 5. 5 UML Notation of Car with Whole-Part Associations ● A Unified Modeling Language (UML) "class diagram" to design aggregated types. – A class diagram underscoring structure, emphases Car's associations: Car Car has Engine and has Tyre. The hollow diamond means "aggregation": the Car is "the whole", but Engine and Tyre are "the parts". This is a note. The class Car. – A class diagram underscoring contents, emphases Car's details: Car - theEngine : Engine* - spareTyre : Tyre* + StartEngine() + GetSpareTyre() : Tyre* + SetSpareTyre() Engine Tyre Car expanded The fields ("attributes" in UML lingo) of Car. The fields are private, mind the "-" notation. The member functions ("operations" in UML lingo) of Car. The member functions are public, mind the "+" notation. – A Car instance aggregates an Engine instance (Not: the UDT Car aggregates the UDT Engine!) ● UML is a language to describe oo systems. ● The class diagram in the structural notation shows the associations. ● The conciser notation shows the details of the types (members, their accessibility etc.). ● The static fields and methods are represented with underlined texts in UML.
  • 6. 6 Expressing Generalization – Specialization in C++ ● Present UDTs can be used as base types for new types. – More special types inherit from more general types. This is called inheritance. ● Instead of "inherits from" we'll occasionally use the phrases "derives from" or "extends". – The data (i.e. the (private) fields) of base types is inherited by the new type. – The behavior (i.e. the member functions) of base types is inherited by the new type. ● The new type inherits the public interface from its base types. ● The inheriting type can access the public interface of its base types but not their private members. – The new type can add more members to the inherited ones. – Where an object of base type was used, an object of the derived type can also be used. ● This is called substitution principle. ● In C++ a new type can inherit from more than one type! – This is called multiple inheritance (MI). We are not going to discuss multiple inheritance! ● Let's learn how inheritance is notated in C++... ● C++' fundamental types and enums can not be used as base types!
  • 7. 7 Inheritance and Type Specialization in C++ ● We've to adorn the class definition of the derived type by naming the base types. – Here we're going to introduce the UDT Bus being inherited from Car. – This inheritance expresses following specialization: a Bus is a Car. // Bus inherits from Car: class Bus : public Car { // (members hidden) static const int COUNT_SEATBENCHES = 42; int nOccupiedSeatBenches; public: bool NewPassengerCanEnter() const { return COUNT_SEATBENCHES <= nOccupiedSeatBenches; } }; ● So let's instantiate and use a Bus: – Mind that we can call Car's inherited and Bus' new member functions on a Bus object. Bus bus; bool hasVacantSeats = bus.NewPassengerCanEnter(); // Accessing a member function of Bus. // Accessing a member function of Bus' base type Car: Tyre spareType = bus.GetSpareTyre(); // Bus inherited (almost) all members of Car. A Bus is a Car. – Ctors of base types are not inherited to the subtype! ● The type Bus is derived from Car. So a Bus is a Car. ● A Bus has 42 seat benches. This means that the count of seat benches is limited. ● A certain count of seat benches (nOccupiedSeatBenches) is occupied by passengers. ● Bus introduces a new public member function NewPassengerCanEnter(). This member function is not present in the base type Car. The interface of Bus then consists of all public members of Car (save Car's ctors) as well as the new public member function NewPassengerCanEnter(). ● Is the type Bus allowed to access theEngine in Car? ● Ctors of base types are not directly inherited to the subtype! But they are called on the creation of a new instance from the most special to the most general type.
  • 8. 8 Sidebar: Non-public Inheritance ● We've used public inheritance in Bus. What happens w/o the public keyword? // Bus inherits from Car non-publicly: class Bus : Car { // (members hidden) }; void StartEngine() { /* pass */ } // Bus inherits from Car privately: class Bus : private Car { // (members hidden) }; class Car { // (members hidden) public: }; ● In this case non-private members of Car are inherited as private members into Bus: Car car; car.StartEngine(); // Ok! Call the public function Car::StartEngine(). Bus bus; bus.StartEngine(); // Invalid! The inherited function Car::StartEngine() can't be called! - It's private in Bus! ● Non-public inheritance is used rarely. – It can be useful with multiple inheritance and to "encapsulate substitutability". ● By default classes apply private inheritance and structs apply public inheritance. ● There also exists protected inheritance. – Its effect can be derived form the effect of private inheritance. ● "Encapsulation of substitutability" means that everywhere a Car was used we can no longer pass a Bus. – Because this "is a" relationship grew private as well!
  • 9. 9 UML Notation of Car with the Specialization Bus ● The UML does also allow designing specialized types in class diagrams: Car Bus - COUNT_SEATBENCHES : int = 42 - nOccupiedSeatBenches : int + NewPassengerCanEnter() : bool Bus inherits Car. The triangular hollow arrow-tip means "inheritance". The constant field "COUNT_SEATBENCHES" is static (it's a "classifier scope member" in UML lingo). static members are underscored in the UML notation. ● In oo, aggregation and specialization associations create a type hierarchy! – This can be nicely shown in UML class diagrams: – We're going to extend this hierarchy during the following discussion. Engine Car Tyre Bus
  • 10. 10 So, what is oo Programming all about? ● The reality can be simulated to a good degree with oo-types! – Most real associations can be expressed with aggregation and specialization. – Even customers can understand, how oo-types function (UML)! ● Thinking in type interfaces rather than in algorithms and procedures: – Interface and implementation can be separated, but types are complete. – First define all interfaces, then implement the type completely. ● Instead of algorithms with functions, we can build architectures with UDTs. – Recurring UDTs architectures are called design patterns. – There exist simple and complex design patterns. ● Successful (oo) programmers identify and use design patterns.
  • 11. 11 Inheritance defines Substitutability ● We discussed that, e.g., a Bus is a Car and we expressed this with inheritance. ● Another way to understand this association: inheritance defines substitutability! – Wherever the UDT Car is awaited, any UDT inherited from Car can be used, e.g. Bus. – Because a Bus is a Car! ● Let's understand this better with an example of substitution. – We'll also introduce another subtype of Car: VintageCar! Car Bus VintageCar Car car; Bus bus; VintageCar vintageCar; Car anotherCar1 = bus; // Aha! We can assign a Bus to a Car object. A Bus is a substitute for a Car. Car anotherCar2 = vintageCar; // We can assign a VintageCar to a Car object. A VintageCar is a // substitute for a Car. Bus anotherBus = vintageCar; // Invalid! A VintageCar is no Bus. VintageCar and Bus are // siblings in the inheritance hierarchy, they don't "know" each // other!
  • 12. nOccupiedSeatBenches spareTyre nOccupiedSeatBenches spareTyre 12 Substitutability and Object Slicing ● The substitution principle as we have used it introduces a problem: slicing. ● When an object of derived type is assigned to an object of base type, the derived type's additional fields are sliced away! – The object bus contains all fields of type Bus: Bus bus; – Assigning bus to the car object slices the object's additional Bus-fields: ● Substitution also works for pointer (and reference) types of inherited types. – But assigning a pointer to another pointer doesn't slice! carPointer still points to a "full" Bus object! ● Using pointers added an extra layer of indirection, which avoids object slicing! bus theEngine car Car car = bus; // Slicing (calls the cctor). Bus* busPointer = &bus; Car* carPointer = &bus; // No slicing! busPointer (Bus) theEngine carPointer
  • 13. 13 Static and dynamic Type of an Object ● On using substitutability with pointers, an object can have a static and a dynamic type. – Originally we used pointers to avoid object slicing with an extra layer of indirection. – The pointer type of the object is the static type of the object. ● The static type is the type of the variable. – The type of the object "behind the pointer" is the dynamic type of the object. – Hence we'll use pointers with dynamic memory allocation to make the difference clear. ● We can cast the dynamic type "out of" the statically typed pointer. – Then we can access the members of the dynamic type. – Objects of varying dynamic type can be referenced by an object of a static type. Car* car = new VintageCar; // Let's point car to a VintageCar. Static type: Car*, dynamic type: VintageCar. VintageCar* vintageCarBehind = static_cast<VintageCar*>(car); // (1) Cast "the VintageCar out of car". vintageCarBehind->CrankUntilStarted(); Bus* busBehind = static_cast<Bus*>(car); // (2) Also ok! Cast "a Bus out of car". But it doesn't work as // intended as car doesn't point to a Bus, it is similar // to "cast contact lenses". – (1) This kind of casting is called "downcasting", as we cast "down the type hierarchy". ● The dynamic type is sometimes called the "run time type". ● The separation of static and dynamic type does also work with C++ references. ● There are languages in which variables have no static type at all, e.g. Smalltalk and JavaScript. ● (2) There is no compile time error, because car could really point to a Bus, because Bus is more special than Car, the compiler just trusts the programmer, downcasting is allowed as both types are related. So the compiler holds the cast to be ok, static_casts are type-checked at compile time. Accessing any member of busBehind, instead those inherited from Car, results in undefined behaviour.
  • 14. 14 The Garage – Car Dependency ● UDTs itself can act as base types to exploit substitutability. – Imagine the recently presented class Car and the new class Garage. – In Garages, Cars are tried to be started with Car's member function StartEngine(). ● The UDT Garage has an association to the UDT Car. – In Garages it should be allowed to start all sorts of Cars. ● Because the behavior of all Cars is the same, however, you can start the engine. – All Cars have the publicized member function StartEngine() in their public interface. ● In UML we can express that "Garage has an association to the UDT Car". – Garage "knows" only about Car! - Nothing about subtypes of Car! Garage + TryToStartCar(car : Car*) Car Bus VintageCar Engine Tyre Garage has an association w/ Car, or: Garage knows about Car. (not vice versa!). The simple arrow with a dashed line expresses this "directed association". ● The term "association": Aggregation and inheritance are nothing but special (and also tighter) associations. ● OO seems to be perfectly good to build GUIs, because the visual representation of GUIs can be directly simulated with oo UDTs and oo paradigms (e.g. "has"- and "is a"-associations of forms and controls). - In opposite to procedural or functional programming.
  • 15. 15 Using Cars in Garages class Garage { // (members hidden) public: ● Now let's inspect the class Garage and its member function TryToStartCar(): – We've just learned that the more special UDT Bus can substitute Car, so this is possible: ● The substitutability allows us to pass more special types toTryToStartCar(). – But calling StartEngine() on the passed car always calls Car::StartEngine()! – We awaited Car::StartEngine() and Bus::StartEngine() to be called! – The problem: StartEngine() is called on the static type, not on the dynamic type! – We should analyze this effect in a more detailed manner... void TryToStartCar(Car* car) const { car->StartEngine(); } }; Garage + TryToStartCar(car : Car*) Garage joesStation; Car* seatLeon = new Car; Bus* mercedesIntegro = new Bus; joesStation.TryToStartCar(seatLeon); // Should call Car's StartEngine(). joesStation.TryToStartCar(mercedesIntegro); // Should call Bus' StartEngine() inherited from Car. ● This example shows how the "substitution principle" allows that the types of a function's arguments (dynamic types) need not to be exactly the types of the declared parameters (static types).
  • 16. 16 The Problem of special Behavior ● To make the mentioned problem visible we'll introduce the UDTVintageCar: – Some VintageCars can only be started with a crank (if they have no starter)! – Let's respect these facts in VintageCar's interface: class VintageCar : public Car { // (members hidden) public: bool CrankUntilStarted() { /* pass */ } bool HasStarter() const { /* pass */ } }; ● Ok, then we're going to give our fordThinLizzie to joesStation: VintageCar* fordThinLizzie = new VintageCar(1909); joesStation.TryToStartCar(fordThinLizzie); // Oops! Calls Car's StartEngine() and this is not enough! // This is no compiler error, but a logical error: the fordThinLizzie can't be started in TryToStartCar()! – Nobody in joesStation knows how to start our fordThinLizzie! – They can't just turn the key and keep going! – The passed Car is a VintageCar (dynamic type) – this is not respected in TryToStartCar(). – Maybe VintageCar is so special that we have to enhance TryToStartCar()?
  • 17. 17 Type Flags to the Rescue ● We can solve the problem by the introduction of a CarType flag field: // An enum for CarType flags: enum CarType { CAR_TYPE, BUS_TYPE, VINTAGE_CAR_TYPE }; ● Let's apply the CarType flag on our Car types: // Add a CarType field to the UDT Car: class Car { // (members hidden) CarType carType; // The type flag. public: CarType GetCarType() const { – How will this help us? => With this flag we can identify the dynamic type of a Car! return carType; } void SetCarType(CarType carType) { this->carType = carType; } }; // Create a Car object and flag it as being of "CAR_TYPE". Car* seatLeon = new Car; seatLeon->SetCarType(CAR_TYPE); // Create a VintageCar object and flag it as being of "VINTAGE_CAR_TYPE". Car* fordThinLizzie = new VintageCar; fordThinLizzie->SetCarType(VINTAGE_CAR_TYPE);
  • 18. 18 Type Flags in Action ● Now we have to modify TryToStartCar() to interpret the CarType flag: void Garage::TryToStartCar(Car* car) const { // If car's CarType flag is VINTAGE_CAR_TYPE start it in a special way: if (VINTAGE_CAR_TYPE == car->GetCarType()) { // Cast the dynamic type "out of" car: VintageCar* vintageCar = static_cast<VintageCar*>(car); // …to access VintageCar's interface: if (!vintageCar->HasStarter()) { vintageCar->CrankUntilStarted(); } else { vintageCar->StartEngine(); } // Else use the default start procedure for other cars: } else { car->StartEngine(); // Start other cars just by calling StartEngine(). } } ● Yes, with this implementation of TryToStartCar() we can start fordThinLizzie: VintageCar* fordThinLizzie = new VintageCar(1909); fordThinLizzie->SetCarType(VINTAGE_CAR_TYPE); joesStation.TryToStartCar(fordThinLizzie); // Ok! TryToStartCar() will pick the correct start-algorithm // depending on the CarType flag!
  • 19. 19 Other special Types need Handling ● After a while the clientele at joesStation grows: – More and more clients bring their diesel cars to joesStation. – But old diesel cars can't be started in Garages! A glowing procedure is required! – As an oo programmer we start by encapsulating the diesel concept into a UDT: Car Bus VintageCar DieselCar ● Btw.: Virtually our type hierarchy is becoming dubious! + Glow() : bool – In fact we needed to redesign the hierarchy, but we're not going to do this in this here! Car Engine DieselEngine OttoEngine Bus VintageCar New aspects: 1. In reality the type of fuel is encapsulated in the Engine! 2. There also exist Buses and VintageCars using diesel fuel. => We can use Engine as an extra level of indirection to handle these aspects.
  • 20. 20 Type Flags are becoming nasty... ● After extending the enum CarType we can modify TryToStartCar() accordingly: void Garage::TryToStartCar(Car* car) const { if (VINTAGE_CAR_TYPE == car->GetCarType()) { /* pass */ } else if(DIESEL_CAR_TYPE == car->GetCarType()) { DieselCar* dieselCar = static_cast<DieselCar*>(car); dieselCar->Glow(); dieselCar->StartEngine(); } else { /* pass */ } } // The CarType flag // DIESEL_CAR_TYPE needs // to be added: enum CarType { // (members hidden) DIESEL_CAR_TYPE }; DieselCar* dieselCar = new DieselCar(); fordThinLizzie->SetCarType(DIESEL_CAR_TYPE); joesStation.TryToStartCar(dieselCar); // Ok! TryToStartCar() will pick the correct start-algorithm! ● This works, but should we really add more CarType flags for upcoming Car types? – Let's remember that we also have to add more else ifs for upcoming Car types! – It's uncomfortable and unprofessional doing the same all over and knowing about that! – This approach is also very error prone! ● Hm... what is the basic problem we've encountered just now?
  • 21. 21 A "Pasta-object-oriented" Hierarchy ● We broke the dependency "Garage – Car" in a negative way! Garage Garage has meanwhile dependencies to Car, and all of Car's subtypes or: Garage knows about all subtypes of Car, and Garage needs to get acquainted to all future subtypes of Car! – Garage needs to know each subtype of Car now and in future! ● We can see this, because Garage::TryToStartCar() inspects the dynamic type of the Car parameter. ● We needed to interpret flags, because we had to deal w/ different interfaces of the dyn. type. ● We have to make downcasts to the dynamic type respectively! ● The bad consequence: Garage::TryToStartCar() must be modified when new Car types emerge! – We can also spot a "bad smell" in the class diagram! ● There are dependencies to the base type Car and to all of its (currently known) subtypes. ● It lead us to spaghetti programming the oo-way! How can we improve that? Car DieselCar VintageCar Bus ● Often too many arrows pointing from a single type to multiple other types is a bad smell. - It can be nicely spotted in a UML class diagram. ● What we've just seen on using enum type flags is called the "typedef-enum-antipattern".
  • 22. 22 Hiding and Overriding ● The idea is to not let Garage::TryToStartCar() select the start algorithm! – Instead, the start algorithm should be put into each individual Car-type! // Starts the Car, special implementation for VintageCars. void VintageCar::StartEngine() { std::cout<<"start VintageCar"<<std::endl; if (HasStarter()) { // Call the hidden StartEngine() in // the base class Car! Car::StartEngine(); } else { while (CrankUntilStarted()) { /* pass */ } } } // Starts the Car, special implementation for // DieselCars. void DieselCar::StartEngine() { std::cout<<"start DieselCar"<<std::endl; Glow(); // Glowing. // Call the hidden StartEngine() in the // base class Car! Car::StartEngine(); } void Garage::TryToStartCar(Car* car) const { car->StartEngine(); // Well, that's a simple implementation! The knowledge and responsibility about // and for the start algorithm is delegated to the dynamic type "behind" car. } ● But it can't work, as we didn't override the member function Car::StartEngine()! joesStation.TryToStartCar(fordThinLizzie); // But... it doesn't work! // >start Car // Car::StartEngine() is called! joesStation.TryToStartCar(new DieselCar); // Doesn't work either! // >start Car // Car::StartEngine() is called! ● Why do we need to call StartEngine() with a Car::-prefix? ● 1. VintageCar could derive from multiple other base types, so one base type needs to be explicitly designated. ● 2. If StartEngine() would be called in VintageCar::StartEngine() it lead to an infinite recursion, because Car::StartEngine() is hidden in VintageCar::StartEngine().
  • 23. 23 Hands on Overriding Member Functions ● Let's concentrate on the UDT DieselCar. – DieselCar can override Car's (DieselCar's base type) member function StartEngine(). – We've to declare overridable functions as virtual member functions in the base type: class Car { public: // Default implementation for Cars. virtual void StartEngine() { std::cout<<"start Car"<<std::endl; theEngine.Start(); // Start directly } }; Car DieselCar class DieselCar : public Car { public: // Special implementation for DieselCars. void StartEngine() { std::cout<<"start DieselCar"<<std::endl; // glowing etc. } }; joesStation.TryToStartCar(new DieselCar); // Works! // >start DieselCar // Hurray! – (If StartEngine() was non-virtual it would only be hidden (not overridden) in derived UDTs.) ● Sometimes the keyword virtual is also written on the overriding methods (in this example it could be written on the method DieselCar::StartEngine()). It's done because of tradition and in order to mark that the method overrides another method. However, it is optional and it will not be checked by the compiler. - We're not going to repeat the virtual keyword on overriding methods in this course's code examples. ● The virtual keyword must not be written on a non-inline definition.
  • 24. 24 Polymorphism – chooses Implementation during Run Time ● The inherited implementation of a member function could be inadequate! – Car::StartEngine() inherited by DieselCar must glow, before starting the Engine! ● Inheriting types can override inherited implementations of member functions. – In C++ overridable member functions must be marked with the virtual keyword. ● virtual member functions are often called methods in C++! ● Overriding (late binding) is not overloading (early binding)! – Overriding takes effect during run time, overloading during compile time! – Overrides in a subtype mustn't change the signature of the overridden method. ● Calling implementations of dynamic types on objects is called oo polymorphism. ● The names of the parameters in an overriding method need no to be same as in the to-be-overridden method.
  • 25. // Trace message instead of implementation. void StartEngine() { 25 Where is Polymorphism happening? ● Whose implementation of method StartEngine() will be called in a Garage? ... ? ? class Garage { public: // Tries to start the passed Car. void TryToStartCar(Car* car) const { car->StartEngine(); // No downcasting! } }; We've the fine class hierarchy back! class Car { public: // Trace message instead of implementation. virtual void StartEngine() { std::cout<<"start Car"<<std::endl; } }; class DieselCar : public Car { public: ● … it is decided during run time, depending on the dynamic type → polymorphically! – The implementation of TryToStartCar() needs never to be modified, if new Car types are introduced! – We applied the dependency inversion principle: Garage only depends on the most abstract type Car! std::cout<<"start DieselCar"<<std::endl; } }; joesStation.TryToStartCar(seatLeon); // >start Car joesStation.TryToStartCar(new DieselCar); // >start DieselCar ? ? Garage Car DieselCar VintageCar ● Which implementation of StartEngine() will be called? ● Car's implementation? ● VintageCar's implementation? ● Polymorphism: ● In future, the implementation of the method StartEngine() of any other sub type of Car could be called! ● In fact, the operator<< as we've overloaded it in a former example uses polymorphism in a similar way StartEngine() does: ● As operator<<'s lhs is of type std::ostream&, it accepts std::cout as well std::ofstreams (so the substitution principle as well as static and dynamic types are exploited). ● When a virtual member function is called, the dynamic type of the object determines, which implementation of that member function is really called. When a non-virtual member function is called, the static type of the object determines, which concrete implementation is called.
  • 26. 26 When to use Inheritance? ● Inheritance can be used to express: – 1. Generalization – specialization associations. ● Bus is more special than Car, this statement justifies inheritance. – 2. The substitution principle and polymorphism. ● Substitution: Whenever a Car is awaited; an object of any inherited UDT can be used. ● Polymorphism: Methods may behave be differently in derived types. – 3. White-box reuse. ● The most important usages are the substitution principle and polymorphism. – It comes along with generalization – specialization associations. – The reuse of the interface (the behavior) is the primary usage aspect! – White-box reuse is a secondary aspect! ● Inheritance for reusing interfaces is the basis for most design patterns.
  • 27. 27 APIE ● The core principles of object orientation can be summarized as "A PIE": – (after Peter van der Linden) A P I E Abstraction Polymorphism Inheritance Encapsulation