Einheitlich initialisieren
In C++03 können einfache Datenstrukturen (vergleichbar zu C-structs) mit Initialisiererlisten initialisiert werden. Dummerweise sperrt man sich damit von den eigentlich interessanten Aspekten von C++ aus: Vererbung, Laufzeitpolymorphie, Konstruktoren… alles verboten. C++11 behebt diesen Mangel. Mit Uniform Initialization lässt sich das Prinzip auf beliebige Datentypen anwenden.
Video
Code
Zuerst die C++03-Variante:
|
|
C++11 verallgemeinert dieses Prinzip stark:
|
|
Erklärung
Das C++03-Beispiel zeigt die Mächtigkeit dieser Initialisierungsart in der main()
-Funktion. Kurz und knackig kann
selbst die verschachtelte Struktur Triangle
mit ihren enthaltenen Points
initialisiert werden. Die Initialisierung
geschieht in der Reihenfolge, in der die Membervariablen in der Klasse stehen: für Point
bekommt x
den ersten, y
den zweiten Wert in der Initialisierliste. Bei Triangle
wird p1
aus dem Point initialisiert, der aus der ersten
Teilliste erzeugt wird und so weiter.
Der Preis für die Bequemlichkeit ist hoch: Point
und Triangle
dürfen nicht von einer anderen Klasse abgeleitet sein,
keine privaten Variablen, keine Konstruktoren und keine virtuellen Funktionen enthalten (es gelten noch ein paar
Detailbedingungen, die aber praktisch wenig relevant sind). Damit sind sie letzten Endes fast normale C-structs, denen
fast alle interessanten C++-Fähigkeiten fehlen (das einzige, was noch übrig bleibt: sie dürfen Member-Funktionen haben).
C++11 verallgemeinert das Prinzip nun. Hier können beliebige Objekte auf diese Art und Weise initialisiert werden. Der Kompiler generiert einfach die passenden Konstruktoraufrufe. Die neue Syntax ist sogar eindeutiger: es gibt Randfälle (bei Bedarf: http://en.wikipedia.org/wiki/Most_vexing_parse), in denen die Konstruktorsyntax zu Uneindeutigkeiten beim Parsing führen kann. Da kann der Compiler dann nicht mehr unterscheiden, ob er eine Variablendeklaration oder eine Funktionsdeklaration vor sich hat. Mit der Uniform Initialization und der neuen Syntax ist das eindeutig: hier werden Variablen initialisiert.
Was für uns aber interessanter ist: wir müssen uns nicht von der Mächtigkeit des C++-Objektsystems verabschieden. Wie
gewohnt können wir ableiten (hier von Shape
), Konstruktoren definieren, private Variablen in einer Klasse haben oder mit
virtuellen Funktionen arbeiten. So kann unser Beispiel zwei hier beispielsweise eine einheitliche Schnittstelle Shape
anbieten und trotzdem von der kurzen Syntax gebrauch machen.