You are on page 1of 31

Proper Use of Polymorphism in C++

Demian Kellermann

June 6, 2011

Polymorphism in C++ Introduction

Everyone here knows how to write class hierarchys But how many of you have ever used private inheritance? And what exactly does public inheritance mean for a design?

Proposal Even experienced programmers tend to overuse (public) inheritance Why? In the following talk I will outline some of the pitfalls of using inheritance and how to design good class hierarchys.

2 / 31

Polymorphism in C++ Introduction

Outline
1 Introduction 2 Interface or Implementation 3 Meaning of Inheritance

Public Inheritance: Is-A Private Inheritance: Is-Implemented-In-Terms-Of Containment vs Inheritance


4 Inheritance vs Templates 5 Uses and Misuses of Multiple Inheritance

Name clashes Siamese Twin Functions Discussion


6 Conclusions
3 / 31

Polymorphism in C++ Interface or Implementation

There are multiple use cases for class inheritance hierarchies: To specify and implement a common interface To extrapolate common functionality in a base class Provide common functionality and default behavior

How are those use cases implemented?

4 / 31

Polymorphism in C++ Interface or Implementation

Interface denitions
Example: Dene an interface to interact with a database
class DatabaseInterface { public : v i r t u a l bool c o n n e c t ( C o n n e c t i o n I n f o &i n f o ) = 0 ; v i r t u a l DataItem q u e r y ( DataQuery &q u e r y ) = 0 ; };

Note Instead of a default implementation, the member functions are pure virtual Classes that only dene pure virtual member functions are called Protocol Classes Inheriting classes must implement their own version of the member functions
5 / 31

Polymorphism in C++ Interface or Implementation

Normal Base Classes


Classes that are intended as base classes may provide mandatory and optional default implementations of member functions.
c l a s s Car { // o p t i o n a l d e f a u l t i m p l e m e n t a t i o n v i r t u a l s t r i n g honk ( ) { r e t u r n Hoooonk ; } // mandatory d e f a u l t i m p l e m e n t a t i o n unsigned i n t g e t S e r i a l N u m b e r ( ) { return serialNum ; } }
6 / 31

Polymorphism in C++ Interface or Implementation

To recapitulate Inheriting classes must implement pure virtual member functions of the base class They may override virtual member functions of the base class They should not override non-virtual member functions Although it is not forbidden...

7 / 31

Overriding non-virtual member functions


Note Never override non-virtual member functions in derived classes
c l a s s Base { void foo ( ) { . . } } c l a s s D e r i v e d : p u b l i c Base { void foo ( ) { . . . } }

D e r i v e d d = new D e r i v e d ( ) ; d>f o o ( ) // D e r i v e d : : f o o ( ) Base b = d ; b>f o o ( ) // Base : : f o o ( )

Polymorphism in C++ Meaning of Inheritance

1 Introduction 2 Interface or Implementation 3 Meaning of Inheritance

Public Inheritance: Is-A Private Inheritance: Is-Implemented-In-Terms-Of Containment vs Inheritance


4 Inheritance vs Templates 5 Uses and Misuses of Multiple Inheritance

Name clashes Siamese Twin Functions Discussion


6 Conclusions
9 / 31

Polymorphism in C++ Meaning of Inheritance Public Inheritance: Is-A

Public Inheritance
To refresh your memory The subclass may access all public and protected members of the base class Public and protected members of the base class become public and protected members of the inheriting class Calling member functions of the base class on a derived object implicitly calls the base class member function Note Public inheritance always represents an IS-A relationship That means any action applicable to the base class must also be applicable to the derived class.
10 / 31

Polymorphism in C++ Meaning of Inheritance Public Inheritance: Is-A

class Rectangle { private : int w; int h ; public : void setWidth ( i n t w) ; void s e t H e i g h t ( i n t h ) ; }; Square s ; s . s e t W i d t h ( 4 2 ) ; // ? !

c l a s s Square : public Rectangle { private : int s ; public : void s e t S i d e s ( i n t s ) ; };

Note Although mathematically correct, a square IS NOT a rectangle when it comes to inheritance
11 / 31

Polymorphism in C++ Meaning of Inheritance Private Inheritance: Is-Implemented-In-Terms-Of

Private Inheritance
Behavior The subclass may access all public and protected members of the base class Public and protected members of the base class become private members of the inheriting class Calling member functions of the base class on a derived object results in a compiler error. Note Private inheritance represents a IS-IMPLEMENTED-IN-TERMS-OF relationship
12 / 31

Polymorphism in C++ Meaning of Inheritance Private Inheritance: Is-Implemented-In-Terms-Of

class Rectangle { private : int w; int h ; public : void setWidth ( i n t w) ; void s e t H e i g h t ( i n t h ) ; };

c l a s s Square : private Rectangle { public : void s e t S i d e s ( i n t s ) { setWidth ( s ) ; setHeight ( s ); } };

Square s ; s . s e t W i d t h ( 4 2 ) ; // C o m p i l e e r r o r s . s e t S i z e ( 2 3 ) ; // w o r k s a s e x p e c t e d

Note The square is now implemented in terms of a rectangle


13 / 31

Polymorphism in C++ Meaning of Inheritance Containment vs Inheritance

Containment vs Inheritance

t e m p l a t e<typename T c l a s s Queue<T > > : p r i v a t e l i s t <T { > public : v o i d e n q u e u e (T &i t e m ) { push back ( item ) } T& d e q u e u e ( ) { return pop front ( ) ; } }

t e m p l a t e<typename T c l a s s Queue<T { > > private : l i s t <T > list ; public : v o i d e n q u e u e (T &i t e m ) { l i s t . push back ( item ) } T& d e q u e u e ( ) { return l i s t . pop front (); } }

The Question Which technique should be preferred?

14 / 31

Polymorphism in C++ Meaning of Inheritance Containment vs Inheritance

Proposal The preferred method to solve IS-IMPLEMENTED-IN-TERMS-OF relations should be Containment Why? Modelling simple HAS-A relationships with private inheritance leads to.. unneccessary compile-time dependencies access to protected members of the base class (violates need to know principle)

15 / 31

Polymorphism in C++ Meaning of Inheritance Containment vs Inheritance

When to use which?


Use private inheritance when you.. need exactly one instance of the base class need access to protected members of the base class need to implement a (pure) virtual member function of the base class want to inuence the construction of a virtual base class benet greatly from emtpy base class optimization Use Containment when you.. need more than one instance of the class you are containing need to change the used instance at runtime do not need to override or implement virtual functions

16 / 31

Polymorphism in C++ Inheritance vs Templates

1 Introduction 2 Interface or Implementation 3 Meaning of Inheritance

Public Inheritance: Is-A Private Inheritance: Is-Implemented-In-Terms-Of Containment vs Inheritance


4 Inheritance vs Templates 5 Uses and Misuses of Multiple Inheritance

Name clashes Siamese Twin Functions Discussion


6 Conclusions
17 / 31

Polymorphism in C++ Inheritance vs Templates

Specialization One might think that inheritance and the template mechanism are two ways to solve similar problems: Create classes dependant on certain types. A look at two examples given by Scott Meyers:

Create dierent classes to manage stacks of certain objects. Each stack may only contain one type of object.

Develop a set of classes representing dierent races of cats. All cats eat and sleep, but they do it dierently.

18 / 31

Polymorphism in C++ Inheritance vs Templates

How do we implement those classes?

Lets try to use templates You can write a stack class without knowing anything about the stored objects You can therefore implement the class with a template parameter T, and return objects of type T You can not write a templated Cat-class, because their behavior depends on the actual type

19 / 31

Polymorphism in C++ Inheritance vs Templates

How do we implement those classes?

OK then, lets try inheritance You can write dierent stack classes for dierent types But you cannot write an abstract base class for them: public virtual ??? pop() = 0; Because the cats need dierent behavior, we implement a protocol class We can then publicly inherit this base class in the classes for dierent breeds

20 / 31

Polymorphism in C++ Inheritance vs Templates

Looking at the problems While the problems seem similar at a rst glance, the main dierence lies in the relationship between the classes and their behavior. Whenever the behavior of your classes depends on actual types, use inheritance When the actual types do not matter, use templates

21 / 31

Polymorphism in C++ Uses and Misuses of Multiple Inheritance

1 Introduction 2 Interface or Implementation 3 Meaning of Inheritance

Public Inheritance: Is-A Private Inheritance: Is-Implemented-In-Terms-Of Containment vs Inheritance


4 Inheritance vs Templates 5 Uses and Misuses of Multiple Inheritance

Name clashes Siamese Twin Functions Discussion


6 Conclusions
22 / 31

Polymorphism in C++ Uses and Misuses of Multiple Inheritance

Pandoras Box? Multiple inheritance, while opening up the modelling process to a more natural approach, introduces problems not existant without it. What problems can arise? Is it still worth it? When should you use multiple inheritance?

23 / 31

Polymorphism in C++ Uses and Misuses of Multiple Inheritance Name clashes

Name clashes

Name ambiguity can be resolved by explicitly naming the class. But this makes virtual member functions non-virtual!

class A { public : void foo ( ) ; }; class B { public : void foo ( ) ; }; c l a s s AB : p u b l i c A , p u b l i c B {};

AB ab ; ab . f o o ( ) ; // C o m p i l e e r r o r ab : : A . f o o ( ) ; //A : : f o o ( ) ab : : B . f o o ( ) ; //B : : f o o ( )

24 / 31

Polymorphism in C++ Uses and Misuses of Multiple Inheritance Siamese Twin Functions

Siamese Twin Functions


Example: You want to implement a graphical lottery simulation. You need to implement a Lottery-interface and an interface for graphical output:

class Lottery { v i r t u a l i n t draw ( ) = 0 ; }

c l a s s Window { v i r t u a l i n t draw ( ) = 0 ; }

The Problem We need to implement both functions dierently, but they have the same signature.
25 / 31

Polymorphism in C++ Uses and Misuses of Multiple Inheritance Siamese Twin Functions

The solution We need to rename the ambiguous functions


c l a s s LotteryDraw : public L o t t e r y { virtual int lotteryDraw () = 0; i n t draw ( ) { // o v e r r i d e return lotteryDraw ( ) ; } } c l a s s WindowDraw : p u b l i c Window { v i r t u a l i n t windowDraw ( ) = 0 ; i n t draw ( ) { // o v e r r i d e r e t u r n windowDraw ( ) ; } }
26 / 31

Polymorphism in C++ Uses and Misuses of Multiple Inheritance Siamese Twin Functions

c l a s s MyLottery : public LotteryDraw , p u b l i c WindowDraw { i n t windowDraw ( ) { . . } int lotteryDraw () {..} }; MyLottery l ; Window lw = & l ; L o t t e r y l l = &l ; lw>draw ( ) ; // windowDraw ( ) l l >draw ( ) ; // l o t t e r y D r a w ( )

27 / 31

Polymorphism in C++ Uses and Misuses of Multiple Inheritance Discussion

Discussion Should you use multiple inheritance? Are there benets or would it be better to exclude it from the next C++ Standard?

Multiple inheritance can be a useful tool, if you know its limitations and problems Combine multiple library classes into a single object Implement multiple protocol classes Make full use of polymorphism

28 / 31

Polymorphism in C++ Conclusions

1 Introduction 2 Interface or Implementation 3 Meaning of Inheritance

Public Inheritance: Is-A Private Inheritance: Is-Implemented-In-Terms-Of Containment vs Inheritance


4 Inheritance vs Templates 5 Uses and Misuses of Multiple Inheritance

Name clashes Siamese Twin Functions Discussion


6 Conclusions
29 / 31

Polymorphism in C++ Conclusions

Say what you mean; understand what youre saying


Think about the relationship of classes before deciding on inheritance Be aware that making member functions non-virtual limits the use of inheriting from your class public inheritance means IS-A private inheritance means IS-IMPLEMENTED-IN-TERMS-OF Only use private inheritance instead of containment if it is neccessary Be aware of the problems of multiple inheritance, but do not be afraid to use it to your advantage
30 / 31

Polymorphism in C++ The End

Thank you for listening


Any questions?

31 / 31

You might also like