Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Inheritance
virtual Operations
static
Design Patterns
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Outline
Recapitulation Copy Constructor & Operators Object-oriented Programming Dynamic and Static Polymorphism The Keyword Static The Singleton Pattern Generic Programming
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Sometimes, we have to rewrite these default operations. For the copy constructor, it is very simple.
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
class.
Bad news: Such a class does already exist. # i n c l u d e <s t r i n g > s t d : : s t r i n g myString0 ; s t d : : s t r i n g myString1 ( h e l l o w o r l d ) ; s t d : : s t r i n g myString2 ( myString1 ) ; s t d : : s t r i n g myString3 = h e l l o MPG ; s t d : : s t r i n g myString4 = myString3 ; myString . l e n g t h ( ) ; myString4 += myString1 ;
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Default Operations
The following operations are generated automatically as public operations if we
dont provide our own implementation: Default constructor. Destructor. Copy constructor.
However, theres still another pitfall: MyString a ; / / do something w i t h a ; MyString b ( a ) ; / / works MyString c ; c = a; / / does n o t work
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Operators
In C++, operators such as +,-,+=,=, are just methods, too. The = operators (assignment operator) is generates automatically, if we dont
overwrite it.
It then is a bit-wise copy of the object. We can redene the operators. We now know, what std : : cout < < stupid < < std : : endl
means.
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Operators RedenedPart I
class Vector { public : / / copy c o n s t r u c t o r V e c t o r ( c o n s t V e c t o r& v e c t o r ) ; V e c t o r& o p e r a t o r =( c o n s t V e c t o r& v e c t o r ) ; / / unary o p e r a t o r s V e c t o r& o p e r a t o r +=( c o n s t V e c t o r& v e c t o r ) ; V e c t o r& o p e r a t o r =( c o n s t double& v a l u e ) ; v o i d toStream ( s t d : : ostream& o u t ) c o n s t ; }; / / binary operators V e c t o r& o p e r a t o r +( c o n s t V e c t o r& l h s , c o n s t V e c t o r& r h s ) ; s t d : : ostream& o p e r a t o r <<(s t d : : ostream& out , c o n s t V e c t o r& v e c t o r ) ; ... V e c t o r& o p e r a t o r +( c o n s t V e c t o r& l h s , c o n s t V e c t o r& r h s ) { Vector r e s u l t ( lhs ) ; r e s u l t += r h s ; return result ; }
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Operators RedenedPart II
class Vector { public : / / copy c o n s t r u c t o r V e c t o r ( c o n s t V e c t o r& v e c t o r ) ; V e c t o r& o p e r a t o r =( c o n s t V e c t o r& v e c t o r ) ; / / unary o p e r a t o r s V e c t o r& o p e r a t o r +=( c o n s t V e c t o r& v e c t o r ) ; V e c t o r& o p e r a t o r =( c o n s t double& v a l u e ) ; v o i d toStream ( s t d : : ostream& o u t ) c o n s t ; }; / / binary operators V e c t o r& o p e r a t o r +( c o n s t V e c t o r& l h s , c o n s t V e c t o r& r h s ) ; s t d : : ostream& o p e r a t o r <<(s t d : : ostream& out , c o n s t V e c t o r& v e c t o r ) ; ... s t d : : ostream& o p e r a t o r <<(s t d : : ostream& out , c o n s t V e c t o r& v e c t o r ) { v e c t o r . toStream ( o u t ) ; r e t u r n out ; }
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
8.3. Inheritance
Sometimes, someone hands you over an object, but this object lacks some
functionality.
Now, it is up to you to add this functionality. However, what happens if there is different variants of this functionality? Image you write a researcher management application. Let Employee be a multi-purpose class for bookkeeping. Task: Add a function setSalary () and getTaxesPaid . However: There are also people getting a stipend. These guys do not pay taxes. Writing two classes is not a variant, as all employees have to have a getWeight()
operation. Challenge: If we duplicate the code, then multiple operations have to be rewritten:
b o o l isBMIAboveThreshold ( ) { ... }
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Challenge Rewritten
A Stipend is an extension of Employee. A PostDoc is an extension of Employee, too. Stipdend and PostDoc are two different things. Whatever we do with an Employee, we can do with a Stipend and PostDoc, too.
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
is aRelations
AbstractDB getEntry()
RealDatabase
HardcodedTestDB
Student has all operations and attributes, Employee has. Every operation expecting an instance of Employee could also be passed an
instance of Student.
Again, we could image this to be an extension of a cut-n-paste mechanism.
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
/ / that s fine
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Object-oriented Programming
is-a relations are mapped to inheritance. Object-based programming becomes object-oriented programming due to this
inheritance concept.
Whenever an object of type A is expected somewhere, we can also pass an object
like private, i.e. they are not visible from outside, but they are visible within subclasses.
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Static Polymorphism
class A { public : void foo ( ) ; }; class B: public A { public : void foo ( ) ; }; A o b j e c t 4 = new A ( ) ; o b j e c t 4 >f o o ( ) ;
C++ implements a static polymorphism by default. It is called static, as the (known) object type determines which operation is to be
invoked.
There is a variant called dynamic polymorphism, too. Java, C# support only dynamic polymorphism.
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Dynamic Polymorphism
class A { public : void foo ( ) ; v i r t u a l v o i d bar ( ) ; }; class B: public A { public : void foo ( ) ; v i r t u a l v o i d bar ( ) ; }; A o b j e c t 1 = new A ( ) ; B o b j e c t 2 = new B ( ) ; A o b j e c t 3 = new B ( ) ; o b j e c t 1 >f o o o b j e c t 2 >f o o o b j e c t 3 >f o o o b j e c t 1 >bar o b j e c t 2 >bar o b j e c t 3 >bar (); (); (); (); (); ();
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Dynamic Destructors
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
This is the reason, C++ introduced initialisation lists, and treats both attributes and super types the same way. Please take care of the order: First, you have to call the supertypes constructor, then you have to initialise your attributes in the right order.
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Multiple inheritance is supported by C++. However, today it is considered to be a bad smell. Theres also a concept called virtual inheritance which is also considered to be a
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Private inheritance is supported by C++. Here, the is-a relationship does not hold anymore, i.e. it is a pure implementation
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Abstract Operations
class A { }; class B: public A { }; c l a s s C: p u b l i c A { };
signature.
Consequently, all operations (in A) have to be virtual. However, it does not make sense to provide any default implementation of an
operation in A.
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Abstract Operations
class A { v i r t u a l void foo ( ) = 0; }; class B: public A { v i r t u a l void foo ( ) ; }; c l a s s C: p u b l i c A { v i r t u a l void foo ( ) ; };
vitual operations can be made abstract. A class with at least one abstract method is an abstract class. We cannot instantiate abstract types. This way, we enforce subclasses to implement them. Classes with solely abstract operations are called interface.
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Variables belong to a scope. Whenever we encounter a variable denition, we reserve memory. At the end of the scope, the variable is destroyed (invoke destructor, free memory).
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Static Variables
void foo ( ) { i n t myInt ; ... } v o i d bar ( ) { s t a t i c i n t myInt ; ... }
Variables belong to a scope. Whenever we encounter a static variable denition for the rst time, we reserve
memory.
A static variable is freed when the application terminates (invoke destructor, free
memory).
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
//
first
c a l l o f bar ( ) ever
Static variables are bind to the application, not to the scope. However, they are still accessible only within the scope. Usuall, (good?) procedural programmers do not use static.
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Object Variables
class A { int field ; void foo ( ) ; }; v o i d A : : f o o ( ) { f i e l d ++; } A instance1 , instance2 ; instance1 . foo ( ) ; instance2 . foo ( ) ;
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Here, static binds the attribute to the class. It is a class attribute. Depending on the visibility, one can either access the static attribute within any operation of A, or even outside of the class (not recommended as it violates the encapsulation idea). If the eld is public, the class acts (from a syntax point of view) similar to a namespace.
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Static Operations
class A { public : void foo ( ) ; s t a t i c v o i d bar ( ) ; }; void A : : foo ( ) { . . . } v o i d A : : bar ( ) { . . . }
We can also declare methods as static. Static methods (class methods) belong to the class, not to an object. Static methods may work on class attributes only.
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
A Factory Method
class A { private : int attribute ; public : s t a t i c A createAnAFromTerminal ( ) ; }; s t a t i c A createAnAFromTerminal ( ) { A result ; std : : cin > > result . attribute ; return A; } ... A myA ; myA = A : : createAnAFromTerminal ( ) ; Static methods may manipulate any attribute of the class as they are part of the
class.
Static methods are called similar to methods wrapped by a namespace. Static methods typically represent operations on sets while methods represent
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
A Singleton
/ Implements a c o n n e c t i o n t o a database ( b i g f i l e ) w i t h l o t s o f material constants . / c l a s s M a t e r i a l C o n s t a n t s {} ;
We want to ensure that MaterialConstants is created only once throughout the application lifecycle. Here are some hints:
MaterialConstants should not have a
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
... M a t e r i a l C o n s t a n t s myDatabase ;
/ / forbidden
We could make all the operations static. However, then we dont have control of the open process. Even worse, this wont t to our fancy new object-oriented paradigm.
8. Object-oriented Programming Introduction to C/C++, Tobias Weinzierl page 36 of 41
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
/ / fine / / forbidden
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
This simple realisation of the static operation works. However, it creates a segmentation fault.
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
This simple realisation of the static operation works. However, it creates a segmentation fault. If we removed the reference symbol, it would create one instance and one copy per call. That is not what we want.
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
A Factory Pattern
type.
This shall be part of a project where
we are promised to get access to the real database by the end of the project. Meanwhile, we have to work with a small number of articial material constants.
Could be switch from one database to
another without changing anything in the code using the material database?
Brain Teaser
Inheritance
virtual Operations
static
Design Patterns
A Factory Pattern
AbstractDB getEntry()
RealDatabase
HardcodedTestDB
We dene an abstract Database type. It is an interface (see UML diagram). This type is delivered by our singleton, i.e. codes work only with the interface. We implement the interface with a stupid class where we hardcode some material