Idiome in der Softwareentwicklung: Polymorphie und Templates
Dieser Beitrag fasst die wichtigsten Fakten zu den in C++ häufig verwendeten Idiomen für Polymorphismus und Templates zusammen.
![](https://heise.cloudimg.io/width/610/q85.png-lossy-85.webp-lossy-85.foil1/_www-heise-de_/imgs/18/3/7/1/1/8/9/7/shutterstock_1067942186-b0eaa584d93e48e4.jpeg)
(Bild: motion.vidos/Shutterstock.com)
- Rainer Grimm
In meiner Artikelserie zu Idiomen in C++ nimmt dieser Beitrag eine Sonderrolle ein, denn ich habe in der jüngeren Vergangenheit bereits an verschiedenen Stellen über Polymorphie und Templates geschrieben. Nun möchte ich aber nochmals die wichtigsten Fakten zu diesen in C++ häufig verwendeten Idiomen zusammenfassen. Um mich dennoch nicht unnötig zu wiederholen, beschränke ich an dieser Stelle darauf, eine kurze Beschreibung des Themas zu präsentieren und auf die ausführlicheren Texte zu verweisen.
Die Idiome für Polymorphismus und Templates spielen in C++ generell eine wichtige Rolle. Beide kommen daher auch häufig zum Einsatz.
Polymorphie
Polymorphie ist die Eigenschaft, die dafür sorgt, dass verschiedene Typen die gleiche Schnittstelle unterstützen können. In C++ wird zwischen dynamischer und statischer Polymorphie unterschieden.
Dynamische Polymorphie
Dynamischer Polymorphismus findet zur Laufzeit statt, er basiert auf der Objektorientierung und ermöglicht die Trennung zwischen der Schnittstelle und der Implementierung einer Klassenhierarchie. Um Late Binding, Dynamic Dispatch oder Dispatch zur Laufzeit zu erreichen, braucht man zwei Zutaten: Virtualität und eine Indirektion wie einen Zeiger oder eine Referenz.
Curiously Recurring Template Pattern (CRTP)
Der Kerngedanke von CRTP ist einfach: Eine Klasse Derived
leitet sich von einem Klassen-Template Base
ab und Base hat Derived
als Template-Argument.
template <typename T>
class Base {
...
};
class Derived : public Base<Derived> {
...
};
Statische Polymorphie
Die statische Polymorphie basiert auf CRTP. Statische Polymorphie erfolgt zur Kompilierzeit und besitzt keine Laufzeitkosten.
Das Overload Pattern
Typischerweise kommt das Overload Pattern für eine std::variant
zum Einsatz. std::variant
ist eine typsichere Union, die einen Wert aus einem ihrer Typen besitzt. std::visit erlaubt es, einen Besucher darauf anzuwenden. Genau hier kommt das Overload Pattern in C++20 sehr praktisch ins Spiel.
template<typename ... Ts>
struct Overload : Ts ... {
using Ts::operator() ... ;
};
- Clevere Tricks zu Parameterpacks und Fold Expressions
- Eine std::variant mit dem Overload Pattern besuchen
Templates
Templates erweitern C++ um viele neue Idiome.
Mixins
Mixins sind eine beliebte Idee beim Entwurf von Klassen, um einen neuen Code hinzuzumischen. Mixins lassen sich in C++ mithilfe von CRTP implementieren. Ein bekanntes Beispiel ist die Klasse std::enable_shared_from_this
.
Expression Templates
Expression Templates werden typischerweise in der linearen Algebra verwendet und sind "structures representing a computation at compile-time, which structures are evaluated only as needed to produce efficient code for the entire computation". Mit anderen Worten: Expression Templates werden nur bei Bedarf ausgewertet.
Temporäre Objekt mit Expression Templates vermeiden
Policy
Eine Policy ist eine generische Funktion oder Klasse, deren Verhalten konfiguriert werden kann. Typischerweise gibt es Standardwerte für die Policy-Parameter. std::vector
und std::unordered_map
sind Beispiele für diese Design-Idee in der Standard Template Library.
template<class T, class Allocator std::allocator<T>>
class vector;
template<class Key,
class T,
class Hash = std::hash<Key>,
class KeyEqual = std::equal_to<Key>,
class allocator = std::allocator<std::pair<const Key, T>>
class unordered_map
Traits
Traits sind Klassen-Templates, die Merkmale eines generischen Typs bereitstellen. Sie können ein oder mehrere Merkmale eines Klassen-Templates extrahieren.
Tag-Dispatching
Tag-Dispatching ist eine Methode zur Simulation von Funktionsüberladung auf der Grundlage von Konzepten, die häufig auf Traits basieren.
Type Erasure
Type Erasure ermöglicht es, verschiedene konkrete Typen mit einer generischen Schnittstelle zu verwenden. In C basiert sie auf void
-Zeigern, in C++ auf der Objektorientierung oder auf Templates.
Wie geht's weiter?
In meinem nächsten Artikel habe ich die Freude, einen Gastbeitrag von Alex Eisenhut präsentieren zu dürfen. Alex wird über seine Leidenschaft berichten: "gute" Softwarearchitektur.
Modernes C++ Mentoring (English)
- "Fundamentals for C++ Professionals": Open
- "Design Patterns and Architectural Patterns in C++": Starts 24/02/2023
Do you want to stay informed about my mentoring programs? Subscribe here
Offene Schulungen (Deutsch)
- C++20: 18.04.2023 - 20.04.2023 (Präsenzschulung)
- Clean Code: Best Practices für modernes C++: 20.06.2023 - 22.06.2023 (Präsenzschulung)
- Design Pattern und Architekturpattern mit C++: 22.08.2023 - 24.08.2023 (Präsenzschulung)
- Embedded Programmierung mit modernem C++: 12.12.2023 - 14.12.2023 (Präsenzschulung)
(map)