summaryrefslogtreecommitdiffhomepage
path: root/de-de/c++-de.html.markdown
blob: 6224d179ab52d6ee034a4d0949aa115a4421686c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
---
language: C++
filename: learncpp-de.cpp
contributors:
    - ["Steven Basart", "http://github.com/xksteven"]
    - ["Matt Kline", "https://github.com/mrkline"]
    - ["Geoff Liu", "http://geoffliu.me"]
    - ["Connor Waters", "http://github.com/connorwaters"]
    - ["Ankush Goyal", "http://github.com/ankushg07"]
    - ["Jatin Dhankhar", "https://github.com/jatindhankhar"]
    - ["Maximilian Sonnenburg", "https://github.com/LamdaLamdaLamda"]
    - ["caminsha", "https://github.com/caminsha"]
lang: de-de
---

C++ ist eine Systemprogrammiersprache die, 

[laut dem Begründer Bjarne Stroustrup](http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Keynote)
entworfen wurde um,

- "besseres C" zu sein
- Datenabstraktion zu unterstützen
- Objektorientierung zu unterstützen
- generische Programmierung zu unterstützen

Durch seine Syntax kann sie durchaus schwieriger und komplexer als neuere Sprachen sein.

Sie ist weit verbreitet, weil sie in Maschinen-Code kompiliert, welcher direkt vom Prozessor ausgeführt
werden kann und somit eine strikte Kontrolle über die Hardware bietet und gleichzeitig
High-Level-Features wie generics, exceptions und Klassen enthält.

Diese Kombination aus Geschwindigkeit und Funktionalität bildet C++ und ist eine der
weitverbreitesten Programmiersprachen.

```c++
//////////////////
// Vergleich zu C
//////////////////

// C ist fast eine Untermenge von C++ und teilt sich grundsätzlich die
// Syntax für Variablen Deklarationen, primitiven Typen und Funktionen.

// Wie in C ist der Programmeinsprungpunkt eine Funktion, welche "main" genannt wird und
// einen Integer als Rückgabetyp besitzt.

// Dieser Wert fungiert als Beendigungsstatus des Programms.
// Siehe: https://de.wikipedia.org/wiki/Return_Code für weitere Informationen
int main(int argc, char** argv)
{
    // Kommandozeilen Argumente werden genauso wie in C über argc und argv übergeben
    // argc entspricht der Anzahl von Argumenten und argv ist ein Array von C-style
    // strings (char*), welche die Argumente repräsentieren.
    // Das erste Argument ist der Name des Programms, welches aufgerufen wird.
    // Argc und argv können, wenn nicht benötigt, weg gelassen werden, indem
    // die Funktionssignatur "int main()" verwendet wird.

    //  Ein Rückgabewert von 0 repräsentiert die erfolgreiche Ausführung.
    return 0;
}

// C++ unterscheidet sich in einigen Punkten von C:

// In C++ sind Zeichen-Literale char´s
sizeof('c') == sizeof(char) == 1

// In C sind Zeichen-Literale int´s
sizeof('c') == sizeof(int)

// C++ verwendet striktes prototyping
void func(); // Funktion ohne Argumente

// In C
void func(); // Funktion mit beliebiger Anzahl von Argumenten

// Verwende nullptr, anstatt von NULL!!!
int* ip = nullptr;

// C standard header sind in C++ verfügbar.
// C header enden mit .h, während
// C++ header das Präfix "c" besitzen und kein ".h" Suffix verwenden.

// Die C++ Standard Version:
#include <cstdio>

// Die C Standard Version:
#include <stdio.h>

int main()
{
    printf("Hello, world!\n");
    return 0;
}

///////////////////////
// Funktionsüberladung
///////////////////////

// C++ unterstützt Funktionsüberladung
// Jede Funktion kann unterschiedliche Parameter erhalten.
void print(char const* myString)
{
    printf("String %s\n", myString);
}

void print(int myInt)
{
    printf("My int is %d", myInt);
}

int main()
{
    print("Hello"); // Wird aufgelöst zu "void print(const char*)"
    print(15); // Wird aufgelöst zu "void print(int)"
}

/////////////////////////////
// Standard Funktionsargumente
/////////////////////////////

// Argumente können per Standard für eine Funktion gesetzt werden,
// wenn diese beim Aufruf nicht bereitgestellt werden.
void doSomethingWithInts(int a = 1, int b = 4)
{
    // führe Anweisungen mit "int´s" aus.
}

int main()
{
    doSomethingWithInts();      // a = 1,  b = 4
    doSomethingWithInts(20);    // a = 20, b = 4
    doSomethingWithInts(20, 5); // a = 20, b = 5
}

// Standard-Argumente müssen am Ende der Liste der Argumente stehen.
void invalidDeclaration(int a = 1, int b) // Fehler!
{
}


/////////////
// Namespaces (Namensräume)
/////////////

// Namespaces stellen einen getrennten Gültigkeitsbereich für Variablen,
// Funktionen und andere Deklarationen zur Verfügung.
// Namespaces können geschachtelt werden.
namespace First
{
    namespace Nested
    {
        void foo()
        {
            printf("This is First::Nested::foo\n");
        }
    } // Ende des Namespace "Nested"
} // Ende des Namespace "First"

namespace Second
{
    void foo()
    {
        printf("This is Second::foo\n");
    }
}

void foo()
{
    printf("This is global foo\n");
}

int main()
{
    // Fügt alle Symbole aus dem namespace Second in den aktuellen Gültigkeitsbereich (scope).
    // "foo()" wird nun nicht länger funktionieren, da es nun doppeldeutig ist, ob foo aus
    // dem namespace foo oder darüberliegenden aufgerufen wird.
    using namespace Second;

    Second::foo(); // Gibt "This is Second::foo" aus.
    First::Nested::foo(); // Gibt "This is First::Nested::foo" aus.
    ::foo(); // Gibt "This is global foo" aus.
}

///////////////
// Eingabe/Ausgabe
///////////////

// C++ verwendet für die Eingabe und Ausgabe streams.
// cin, cout und cerr repräsentieren stdin, stdout und stderr.
// << ist der Einfügeoperator und >> ist der Extraktionsoperator.

#include <iostream> // Include für Eingabe/Ausgabe (I/O) streams

using namespace std; // Streams befinden sich im std namespace (standard library)

int main()
{
   int myInt;

   // Ausgabe auf stdout (oder Terminal/Bildschirm)
   cout << "Enter your favorite number:\n";

   // Empfängt Eingabe
   cin >> myInt;

   // cout kann ebenfalls formatiert werden
   cout << "Your favorite number is " << myInt << "\n";
   // Gibt "Your favorite number is <myInt>" aus

    cerr << "Used for error messages";
}

//////////
// Zeichenketten (Strings)
//////////

// Strings in C++ sind Objekte und haben diverse member-functions
#include <string>

using namespace std; // Strings sind ebenfalls im namespace std (Standard Bibliothek)

string myString = "Hello";
string myOtherString = " World";

// + wird für das Anhängen von strings verwendet.
cout << myString + myOtherString; // "Hello World"

cout << myString + " You"; // "Hello You"

// C++ strings sind mutable.
myString.append(" Dog");
cout << myString; // "Hello Dog"


/////////////
// Referenzen
/////////////

// Zusätzlich zu Pointern, wie jene in C.
// C++ besitzt _Referenzen_.
// Diese sind Pointer-Typen, welche nicht erneut zugewiesen werden können
// und nicht Null sein können.
// Sie besitzen den selben Syntax wie Variablen.
// Für die Dereferenzierung ist kein * notwendig und
// & (die Adresse) wird nicht für die Zuweisung verwendet.

using namespace std;

string foo = "I am foo";
string bar = "I am bar";


string& fooRef = foo; // Erzeugt eine Referenz auf foo.
fooRef += ". Hi!"; // Verändert foo durch die Referenz
cout << fooRef; // Gibt "I am foo. Hi!" aus.


// Weist "fooRef" nicht erneut zu. Dies ist dasselbe, wie "foo = bar" und 
// foo == "I am bar"
// nach dieser Zeile 
cout << &fooRef << endl; // Gibt die Adresse von foo aus
fooRef = bar;
cout << &fooRef << endl; // Gibt ebenfalls die Adresse von foo aus
cout << fooRef;  // Gibt "I am bar" aus

// Die Adresse von fooRef verbleibt die selbe, sie verweist immer noch auf foo

const string& barRef = bar; // Erzeugt konstante Referenz auf bar.
// Wie in C, können konstante Werte ( und Pointer bzw. Referenzen) nicht verändert werden.

barRef += ". Hi!"; // Fehler: konstante Referenzen können nicht verändert werden.

// Hinweis: bevor wir genauer Referenzen besprechen, schauen wir uns zuerst ein Konzept an,
// welches als "temporäres Objekt" bezeichnet wird. Gehen wir von folgenden Code aus:
string tempObjectFun() { ... }
string retVal = tempObjectFun();

// Was passiert nun in der zweiten Zeile:
//  - ein String Objekt wird von "tempObjectFun" zurückgegeben
//  - ein neuer String wird mit dem zurückgegebenen Objekt als Argument für den Konstruktor erzeugt.
//  - das zurückgegebene Objekt wird zerstört
// Das zurückgegbene Objekt wird temporäres Objekt genannt. Temporäre Objekte werden erzeugt
// wann immer eine Funktion ein Objekt zurückgibt. Zerstört werden diese am Ende der Auswertung des Ausdrucks
// (dies schreibt der Standard vor, aber Compiler sind berechtigt dieses Verhalten zu ändern. Siehe "return value optimization"
// für Details). Wie in diesem Code:
foo(bar(tempObjectFun()))

// Nehmen wir an, foo und bar existieren. Das Objekt wird von "tempObjectFun" zurückgegeben,
// wird an bar übergeben und ist zerstört bevor foo aufgerufen wird.

// Zurück zu Referenzen. Die Annahme, dass die "am Ende des Ausdrucks" Regel gültig ist,
// wenn das temporäre Objekt an eine konstante Referenz gebunden ist, ist der Fall, wenn die Lebensdauer
// auf den aktuellen Gültigkeitsbereich erweitert wird.

void constReferenceTempObjectFun() {
  // constRef erhält das temporäre Objekt und ist gültig bis ans Ende der Funktion
  const string& constRef = tempObjectFun();
  ...
}

// Eine andere Art von Referenzen wurde in C++11 eingeführt und ist speziell für
// temporäre Objekte. Es ist nicht möglich Variablen des Typs zu besitzen, aber
// Vorrechte bei der Auflösung zu besitzen.

void someFun(string& s) { ... }  // Reguläre Referenz
void someFun(string&& s) { ... }  // Referenz auf ein temporäres Objekt

string foo;
someFun(foo);  // Ruft die Funktion mit der regulären Referenz auf
someFun(tempObjectFun());  // Ruft die Funktion mit der temporären Referenz auf

// Zum Beispiel existieren diese zwei Varianten von Konstruktoren für
// std::basic_string:
basic_string(const basic_string& other);
basic_string(basic_string&& other);

// Nehmen wir an, wir erzeugen einen neuen String eines temporären Objekts (welches später
// zerstört wird), hierbei existiert ein effizienterer Konstruktor. Dieses Konzept wird
// als "move semantics" bezeichnet (bewegen eines Objekts in ein anderes in C++).

/////////////////////
// Enumerations (Aufzählungstypen)
/////////////////////

// Enums sind eine einfachere Art und Weise einen Wert einer Konstante zu zuweisen.
// Häufig wird dies verwendet, um den Code lesbarer zu gestalten bzw. zu visualisieren.
enum ECarTypes
{
  Sedan,
  Hatchback,
  SUV,
  Wagon
};

ECarTypes GetPreferredCarType()
{
	return ECarTypes::Hatchback;
}

// Mit C++11 existiert eine einfache Möglichkeit einem Typ dem Enum zuzuweisen. Dies
// kann durchaus sinnvoll bei der Serialisierung von Daten sein, oder bei der Konvertierung
// zwischen Typen bzw. Konstanten.
enum ECarTypes : uint8_t
{
  Sedan, // 0
  Hatchback, // 1
  SUV = 254, // 254
  Hybrid // 255
};

void WriteByteToFile(uint8_t InputValue)
{
    // Serialisierung von "InputValue" in eine Datei
}

void WritePreferredCarTypeToFile(ECarTypes InputCarType)
{
    // Das enum wird implizit zu einem "uint8_t" konvertiert. Bedingt dadurch, dass
    // es sich um ein "enum" handelt.
	WriteByteToFile(InputCarType);
}

// Nicht immer ist es gewünscht, dass enum´s zu einem Integer oder zu einem anderen
// enum umgewandelt werden. Daher ist es möglich eine enum-Klasse zu erzeugen, welche
// nicht implizit umgewandelt wird.
enum class ECarTypes : uint8_t
{
  Sedan, // 0
  Hatchback, // 1
  SUV = 254, // 254
  Hybrid // 255
};

void WriteByteToFile(uint8_t InputValue)
{
    // Serialisierung von InputValue in eine Datei
}

void WritePreferredCarTypeToFile(ECarTypes InputCarType)
{
  // Wird nicht kompilieren, da "ECarTypes" ein "uint8_t" ist, da das enum
  // als "enum class" deklariert wurde!
	WriteByteToFile(InputCarType);
}

//////////////////////////////////////////
// Klassen und objekorientierte Programmierung
//////////////////////////////////////////

// Erstes Beispiel einer Klasse
#include <iostream>

// Deklaration einer Klasse.
// Klassen werden üblicherweise im header (.h oder .hpp) deklariert.
class Dog
{
    // Member Variablen und Funktionen sind private per default (standard).
    std::string name;
    int weight;

// Alle nachfolgenden member sind "public" bis
// "private:" oder "protected:" auftritt.
public:

    // Standard Konstruktor
    Dog();

    // Member-Funktionsdeklaration (Implementierung folgt).
    // Bemerkung: std::string statt der Verwendung von namespace std;
    // "using namespace" sollte niemals in einem header verwendet werden.
    void setName(const std::string& dogsName);

    void setWeight(int dogsWeight);

    // Funktionen, die Objekte nicht ändern, sollten mit const deklariert werden.
    // Funktionen müssen explizit als "virtual" deklariert werden, um in einer
    // abgeleiteten Klassen überschrieben zu werden.
    // Aus performance Gründen sind Funktionen nicht per default virtual.
    virtual void print() const;

    // Funktionen können ebenfalls im class body definiert werden.
    // Derart definierte Funktionen sind automatisch "inline".
    void bark() const { std::cout << name << " barks!\n"; }

    // Neben Konstruktoren, bietet C++ Destruktoren.
    // Diese werden aufgerufen, wenn ein Objekt freigegeben wird oder
    // seinen Wertebereich verlässt.
    // Dies ermöglicht mächtige Paradigmen, wie auch RAII.
    // Destruktoren sollten virtual sein, wenn eine Klasse von ihr
    // abgeleitet wird. Ist dieser nicht virtual, dann wird der
    // Destruktor der abgeleiteten Klasse nicht aufgerufen, insofern
    // das Objekt durch eine Referenz/Pointer der Basisklasse entfernt wird.
    virtual ~Dog();

}; // Ein Semikolon schließt die Definition der Klasse ab.  

// Klassen-Member-Funktionen sind üblicherweise in der .cpp Datei implementiert.
Dog::Dog()
{
    std::cout << "A dog has been constructed\n";
}

// Objekte sollten als Referenz übergeben werden und wenn diese nicht
// verändert werden sollen, sollte das Objekt als const Referenz übergeben werden.
void Dog::setName(const std::string& dogsName)
{
    name = dogsName;
}

void Dog::setWeight(int dogsWeight)
{
    weight = dogsWeight;
}

// "Virtual" wird nur bei der Deklaration benötigt und nicht bei der Definition.
void Dog::print() const
{
    std::cout << "Dog is " << name << " and weighs " << weight << "kg\n";
}

Dog::~Dog()
{
    std::cout << "Goodbye " << name << "\n";
}

int main() 
{
    Dog myDog; // Ausgabe: "A dog has been constructed"
    myDog.setName("Barkley");
    myDog.setWeight(10);
    myDog.print(); // Ausgabe: "Dog is Barkley and weighs 10 kg"
    return 0;
} // Ausgabe: "Goodbye Barkley"

// Diese Klasse erbt alles was public bzw. protected ist von der Dog-Klasse
// und darüber hinaus auch private Methoden/Attribute, jedoch kann auf diese
// nicht direkt zugegriffen werden. Lediglich über public/procted getter/setter.
class OwnedDog : public Dog {

public:
    void setOwner(const std::string& dogsOwner);

    // Überschreibt das Verhalten der "print" Funktion für alle "OwnedDogs".
    // Siehe: http://en.wikipedia.org/wiki/Polymorphism_(computer_science)#Subtyping
    // für eine grundlegende Einführung in "Subtype Polymorphismus".
    // Das "override" Schlüsselwort ist optional, aber stellt sicher, dass die
    // Methode der Basisklasse tatsächlich überschrieben wurde.
    void print() const override;

private:
    std::string owner;
};

// Die zugehörige .cpp Datei
void OwnedDog::setOwner(const std::string& dogsOwner)
{
    owner = dogsOwner;
}

void OwnedDog::print() const
{
    Dog::print(); // Ruft die "print" Funktion der Basisklasse auf.
    std::cout << "Dog is owned by " << owner << "\n";
    // Ausgaben: "Dog is <name> and weights <weight>"
    //           "Dog is owned by <owner>"
}

//////////////////////////////////////////
// Initialisierung und Operatorüberladung
//////////////////////////////////////////

// In C++ können Operatoren wie: +, -, *, / etc. überladen werden.
// Dies wird umgesetzt, indem eine entsprechende Funktion definiert wird,
// welche immer dann aufgerufen wird, sobald der Operator verwendet wird.
#include <iostream>
using namespace std;

class Point
{
public:
    // Member Variablen können mit einem default Wert initialisiert werden.
    double x = 0;
    double y = 0;

    // Definition des Standard Konstruktor, welcher nichts tut
    // außer den Punkt auf den default Wert (0,0) zu setzen.
    Point() { };

    // Die nachfolgende Syntax ist bekannt als "initialization list"
    // und ist eine gängige Art Klassen-Member zu initialisieren.
    Point (double a, double b) :
        x(a),
        y(b)
    { /* Außschließliche Initialisierung der Werte */ }

    // Überladung des "+" Operator.
    Point operator+(const Point& rhs) const;

    // Überladung des "+=" Operator
    Point& operator+=(const Point& rhs);

    // Sinnhaft wäre es an dieser Stelle den "-" und "-=" Operator
    // ebenfalls zu überladen.
};

Point Point::operator+(const Point& rhs) const
{
    // Erzeugung eines neuen Punkts, welcher die Summe aus sich
    // selbst und "rhs" bildet
    return Point(x + rhs.x, y + rhs.y);
}

Point& Point::operator+=(const Point& rhs)
{
    x += rhs.x;
    y += rhs.y;
    return *this;
}

int main ()
{
    Point up (0,1);
    Point right (1,0);

    // Ruft den + Operator mit den entsprechenden Parametern auf.
    Point result = up + right;
    // Ausgabe: "Result is upright (1,1)"
    cout << "Result is upright (" << result.x << ',' << result.y << ")\n";
    return 0;
}

/////////////////////
// Templates
/////////////////////

// Templates in C++ werden in erster Linie dafür verwendet generisch zu programmieren.
// Sie unterstützen explizite und partielle Spezialisierung und darüber hinaus können
// sie für funktionale Klassen verwendet werden.
// Tatsächlich bilden Templates die Turing-Vollständigkeit
// (universelle Programmierbarkeit) ab.


// Zu Beginn ein einführendes Beispiel der generischen Programmierung.
// Die Definition einer Klasse bzw. Funktion, welche mit dem Typ T parametriert wird.
template<class T>
class Box
{
public:
    // T repräsentiert an dieser Stelle einen beliebigen Typen.
    void insert(const T&) { ... }
};

// Während der Kompilierung generiert der Compiler Kopien für jedes Template, wobei
// hierbei die Parameter substituiert werden. Somit muss bei jedem Aufruf die gesamte
// Definition der Klasse zur Verfügung stehen. Aus diesem Grund wird ein Template
// komplett im header definiert.

// Erzeugung einer Template-Klasse auf dem Stack:
Box<int> intBox;

// eine der zu erwartenden Verwendungen:
intBox.insert(123);

// Verschachtelungen von Templates sind möglich.
Box<Box<int> > boxOfBox;
boxOfBox.insert(intBox);

// Bis C++11 war es erforderlich ein Leerzeichen zwischen '>' einzufügen,
// andernfalls wurde es als '>>' geparsed (right shift).

// Manchmal ist folgende Notation anzutreffen:
// template<typename T>
// Das 'class' Schlüsselwort und das 'typename' Schlüsselwort
// sind fast identisch hinsichtlich der Funktionalität. Weitere
// Informationen auf: http://en.wikipedia.org/wiki/Typename

// Eine Template-Funktion:
template<class T>
void barkThreeTimes(const T& input)
{
    input.bark();
    input.bark();
    input.bark();
}

// Hierbei ist zu beachten, dass an dieser Stelle nichts über den Typen des Parameters
// definiert wurde. Der Compiler wird bei jedem Aufruf bzw. jeder Erzeugung den Typen
// prüfen. Somit funktioniert die zuvor definierte Funktion für jeden Typ 'T', die die
// const Methode 'bark' implementiert hat.

Dog fluffy;
fluffy.setName("Fluffy")
barkThreeTimes(fluffy); // Gibt "Fluffy barks" dreimal aus.

// Template Parameter müssen keine Klassen sein.
template<int Y>
void printMessage()
{
  cout << "Learn C++ in " << Y << " minutes!" << endl;
}

// Des Weiteren können Templates aus Effizienzgründen genauer spezifiziert werden.
// Selbstverständlich sind reale Probleme, welche genauer spezifiziert werden, nicht
// derart trivial. Auch wenn alle Parameter explizit definiert wurden, muss die
// Funktion oder Klasse als Template deklariert werden.
template<>
void printMessage<10>()
{
  cout << "Learn C++ faster in only 10 minutes!" << endl;
}

printMessage<20>();  // Gibt "Learn C++ in 20 minutes!" aus.
printMessage<10>();  // Gibt "Learn C++ faster in only 10 minutes!" aus.


/////////////////////
// Ausnahme Behandlungen (Exception-Handling)
/////////////////////

// Die Standard Bibliothek bietet einige exceptions.
// Siehe: http://en.cppreference.com/w/cpp/error/exception.
// Grundsätzlich können alle Typen als exception geworfen werden.
#include <exception>
#include <stdexcept>

// Alle exceptions, die in dem "try" Block geworfen werden, können mittels
// "catch" abgefangen werden.
try
{
    // exceptions sollten nicht auf dem heap mithilfe
    // von "new" allokiert werden.
    throw std::runtime_error("A problem occurred");
}

// Exceptions sollten als const Referenz abgefangen werden
// insofern diese Objekte sind.
catch (const std::exception& ex)
{
    std::cout << ex.what();
}

// Abfangen aller Exceptions, welche zuvor nicht abgefangen wurden.
catch (...)
{
    std::cout << "Unknown exception caught";
    throw; // Erneutes werfen der exception
}

///////
// RAII
///////

// RAII steht für "Resource Acquisition Is Initialization".
// Oft wird dies als eines der wichtigsten Paradigmen in C++ betrachtet.
// RAII beschreibt das Konzept, dass der Konstruktor für ein Objekt
// die Ressourcen akquiriert und der Destruktor diese freigibt.

// Zum Verständnis, warum dies sinnvoll ist, nachfolgend
// ein einführendes Beispiel:
void doSomethingWithAFile(const char* filename)
{
    // Wir nehmen an, dass nichts schiefgehen wird.
    FILE* fh = fopen(filename, "r"); // Öffnen der Datei im read-mode.

    doSomethingWithTheFile(fh);
    doSomethingElseWithIt(fh);

    fclose(fh); // Schließen des file-handle.
}

// Unglücklicherweise ist die Fehlerbehandlung äußerst kompliziert.
// Sollte fopen fehlschlagen und "doSomethingWithTheFile" bzw.
// "doSomethingElseWithIt", geben diese einen Fehlercode zurück.
// (Exceptions sind eine bevorzugte Möglichkeit Fehler abzufangen
// , allerdings bei einigen Programmierern, besonders solchen die einen C
// background besitzen, ein unbeliebtes Mittel zur Fehlerbehandlung).
// Nun müssen wir jeden Aufruf auf mögliche auftretende Fehler überprüfen.
bool doSomethingWithAFile(const char* filename)
{
    FILE* fh = fopen(filename, "r"); // Öffnet die Datei im read-mode
    if (fh == nullptr) // Der Pointer ist bei einem Fehler NULL .
        return false; // Benachrichtigt den Aufrufer über den Fehler.

    // Wir nehmen an, dass jede Funktion false zurückgibt, in einem Fehlerfall
    if (!doSomethingWithTheFile(fh))
    {
        fclose(fh); // File handle schließen.
        return false; // Fehler "melden".
    }

    if (!doSomethingElseWithIt(fh))
    {
        fclose(fh); // File handle schließen.
        return false; // Fehler "melden".
    }

    fclose(fh); // File handle schließen.
    return true; // Erfolg "melden".
}

// C-Programmierer handhaben dies häufig durch goto-Anweisungen:
bool doSomethingWithAFile(const char* filename)
{
    FILE* fh = fopen(filename, "r");
    if (fh == nullptr)
        return false;

    if (!doSomethingWithTheFile(fh))
        goto failure;

    if (!doSomethingElseWithIt(fh))
        goto failure;

    fclose(fh); // File handle schließen.
    return true; // Erfolg "melden".

failure:
    fclose(fh);
    return false; // Fehler "melden".
}

// Insofern Funktionen Fehler durch exceptions indizieren,
// ist dies "sauberer", aber immer noch suboptimal.
void doSomethingWithAFile(const char* filename)
{
    FILE* fh = fopen(filename, "r"); // Öffnet die Datei im read-mode
    if (fh == nullptr)
        throw std::runtime_error("Could not open the file.");

    try
    {
        doSomethingWithTheFile(fh);
        doSomethingElseWithIt(fh);
    }
    catch (...)
    {
        // Im Fehlerfall sollte sichergestellt sein, dass die
        // Datei geschlossen wird.
        fclose(fh);
        throw; // Erneutes werfen der exception
    }

    fclose(fh); // Schließen der Datei
}

// Folgendes ist mit der C++ file stream Klasse (fstream) zu vergleichen.
// fstream verwendet den Destruktor, um die Datei zu schließen.
// Der obige Destruktor wird automatisch aufgerufen, sobald das Objekt
// den Gültigkeitsbereich verlässt.
void doSomethingWithAFile(const std::string& filename)
{
    // ifstream entspricht der Kurzform von "input file stream".
    std::ifstream fh(filename); // Öffnen der Datei

    doSomethingWithTheFile(fh);
    doSomethingElseWithIt(fh);

} // Die Datei wird automatisch vom Destruktor geschlossen.

// Diese Vorgehensweise bietet massive Vorteile:
// 1. Egal was passiert, die Ressource (das Datei-Handle) wird aufgelöst,
//    insofern der Destruktor korrekt beschrieben wurde. Es ist möglich
//    zu vergessen das Datei-Handle zu schließen, was zu einem "leak" der
//    entsprechenden Ressource führt.
// 2. Der Code selbst ist wesentlich "sauberer".
//    Der Destruktor wird das Datei-Handle im Hintergrund schließen und der
//    Programmierer muss sich darum keinerlei Sorgen machen.
// 3. Der Code ist "exception sicher".
//    Egal wo die exception geworfen wird, das Aufräumen wird definitiv vollzogen.

// Der gesamte idiomatische C++ Code verwendet RAII für alle Ressourcen.
// Weitere Beispiele:
// - Speicher verwenden "unique_ptr" und "shared_ptr".
// - Container - verkettete Listen (linked list), vector (selbst organisierende
//   Arrays), hash maps, etc., entfernen deren Inhalt, wenn diese außerhalb des
//   Gültigkeitsbereichs laufen.
// - Mutex´s verwenden lock_guard und unique_lock.

/////////////////////
// Container
/////////////////////

// Die Container der Standard template Bibliothek beinhaltet einige vordefinierte Templates.
// Diese verwalten die Speicherbereiche für die eigenen Elemente und stellen Member-Funktionen
// für den Zugriff und die Manipulation bereit.

// Beispielhafte Container:

// Vector (dynamisches array)
// Erlaubt das Definieren von Arrays oder Listen zur Laufzeit
#include <vector>
string val;
vector<string> my_vector; // Initialisierung des Vectors.
cin >> val;
my_vector.push_back(val); // Fügt den Wert "val" zum Vektor "my_vector" hinzu.
my_vector.push_back(val); // Fügt den Wert "val" zum Vektor "my_vector" hinzu (nun zwei Elemente).

// Für die Iteration über Vektoren stehen zwei Methodiken zu Verfügung:
// Entweder die klassische Iteration über den Index:
for (int i = 0; i < my_vector.size(); i++)
{
	cout << my_vector[i] << endl; // Zugriff auf die Elemente des Vektors über den [] Operator
}

// Oder die Verwendung von Iteratoren:
vector<string>::iterator it; // Initialisierng des Iterators.
for (it = my_vector.begin(); it != my_vector.end(); ++it)
{
	cout << *it  << endl;
}

// Set (Mengen)
// Sets sind Container, welche einzigartige Elemente beinhalten die einer
// spezifischen Ordnung folgen.

#include<set>
set<int> ST;    // Initialisierung des Sets mit einem Integer Datentyp.
ST.insert(30);  // Einfügen des Werts 30 in das Set ST
ST.insert(10);  // Einfügen des Werts 10 in das Set ST
ST.insert(20);  // Einfügen des Werts 20 in das Set ST
ST.insert(30);  // Einfügen des Werts 30 in das Set ST
// Folgende Elemente befinden sich nun in dem Set:
//  10 20 30

// Entfernen eines Elements:
ST.erase(20);

// Set ST: 10 30
// Für das iterieren verwenden wir Iteratoren:
set<int>::iterator it;

for(it=ST.begin();it<ST.end();it++)
{
	cout << *it << endl;
}

// Ausgabe:
// 10
// 30

// Zum leeren des gesamten Containers wird die Methode
// Container._name.clear() verwendet.
ST.clear();
cout << ST.size();  // Ausgabe der Set-Größe

// Ausgabe: 0

// Bemerkung: für mehrdeutige Elemente werden multisets verwendet.
// Für hash-Sets sollten unordered_set´s verwendet werden, da diese
// wesentlich effizienter sind, allerdings keiner Ordnung folgen.
// Verfügbar sind diese Features ab C++11.

// Map
// Maps speichern Elemente, welche einer Kombination aus "Key"
// und "Value" folgen.

#include<map>
map<char, int> mymap;  // Initialisierung der Map: char -> Key, int -> Value.

mymap.insert(pair<char,int>('A',1)); // Einfügen des Werts "1" für den Key "A".

mymap.insert(pair<char,int>('Z',26)); // Einfügen des Werts "26" für den Key "Z".

// Das Iterieren über Maps:
map<char,int>::iterator it;
for (it=mymap.begin(); it!=mymap.end(); ++it)
    std::cout << it->first << "->" << it->second << '\n';

// Ausgabe:
// A->1
// Z->26

// Für das Finden des dazugehörigen Value des Keys.
it = mymap.find('Z');
cout << it->second;

// Ausabe: 26

// Bemerkung: für "hash maps" sollten die "unordered_map´s" verwendet werden. Diese
// sind effizienter und benötigen keine Reihenfolge. "unordered_maps" sind ab
// C++11 verfügbar.

// Container für nicht-primitive Datentypen benötigen Vergleichsfunktionen im Objekt selbst,
// oder als Funktionspointer. Primitive Datentypen besitzen default-Vergleichsfunktionen.
// Allerdings können diese überschrieben werden.
class Foo
{
public:
    int j;
    Foo(int a) : j(a) {}
};

struct compareFunction
{
    bool operator()(const Foo& a, const Foo& b) const
    {
        return a.j < b.j;
    }
};

// Folgender Code ist nicht valide, könnte aber von einigen Compilern
// als valide angesehen werden:
// std::map<Foo, int> fooMap;
std::map<Foo, int, compareFunction> fooMap;
fooMap[Foo(1)]  = 1;
fooMap.find(Foo(1)); // Wahr


///////////////////////////////////////
// Lambda Ausdrücke (C++11 und höher)
///////////////////////////////////////

// Lambdas sind eine gängige Methodik, um anonyme Funktionen an dem
// Ort der Verwendung zu definieren. Darüber hinaus auch bei der
// Verwendung von Funktionen als Argument einer Funktion.

// Nehmen wir an, es soll ein Vektor von "pairs" (Paaren) mithilfe
// des zweiten Werts des "pairs" sortiert werden.

vector<pair<int, int> > tester;
tester.push_back(make_pair(3, 6));
tester.push_back(make_pair(1, 9));
tester.push_back(make_pair(5, 0));

// Übergabe des Lambda-Ausdrucks als drittes Argument für die nachfolgende Sortierfunktion.
sort(tester.begin(), tester.end(), [](const pair<int, int>& lhs, const pair<int, int>& rhs)
{
        return lhs.second < rhs.second;
});

// Beachte die Syntax von Lambda-Ausdrücken.
// Die [] im Lambda Ausdruck werden für die Variablen verwendet.
// Diese so genannte "capture list" definiert, was außerhalb des Lambdas,
// innerhalb der Funktion verfügbar sein soll und in welcher Form.
// Dies kann folgendes sein:
//     1. ein Wert [x]
//     2. eine Referenz [&x]
//     3. eine beliebige Variable, welche sich im Gültigkeitsbereich durch
//        die Referenz [&] befindet.
//     4. wie bei 3. aber mithilfe des Werts [=]
// Beispiel:

vector<int> dog_ids;

for(int i = 0; i < 3; i++)
{
	dog_ids.push_back(i);
}

int weight[3] = {30, 50, 10};

// Nehmen wir an wir möchten die "dog_ids" gemäß des Gewichts des Hundes sortieren.
// So sollten sich die "dog_ids" wie folgt verhalten: [2, 0, 1]

// Hier werden Lambdas praktisch:
sort(dog_ids.begin(), dog_ids.end(), [&weight](const int &lhs, const int &rhs)
{
        return weight[lhs] < weight[rhs];
});


// Weiterführender Link über Lambda-Ausdrücke:
// http://stackoverflow.com/questions/7627098/what-is-a-lambda-expression-in-c11

///////////////////////////////
// Range For (C++11 und höher)
///////////////////////////////

// Range-For Schleifen können verwendet werden, um über Container zu iterieren.
int arr[] = {1, 10, 3};

for(int elem: arr)
{
	cout << elem << endl;
}

// Insofern "auto" verwendet wird, muss der Typ nicht weiter beachtet werden.
for(auto elem: arr)
{
	// Anweisungen ...
}

/////////////////////
// Weiteres:
/////////////////////

// Einige Aspekte von C++ sind für Neueinsteiger häufig überraschend (aber auch für
// C++ Veteranen).
// Der nachfolgende Abschnitt ist leider nicht vollständig:
// C++ ist eine der Sprachen, bei der es ein Leichtes ist, sich selbst ins Bein zu schießen.

// Private-Methoden können überschrieben werden
class Foo
{
  virtual void bar();
};

class FooSub : public Foo
{
  virtual void bar();  // Überschreibt Foo::bar!
};

// 0 == false == NULL
bool* pt = new bool;
*pt = 0; // Setzt den Wert des Pointers 'pt' auf false.
pt = 0;  // Setzt 'pt' auf den "null-pointer". Keine Compiler-Warnung.

// nullptr sollte dieses Problem nicht lösen:
int* pt2 = new int;
*pt2 = nullptr; // Kompiliert nicht.
pt2 = nullptr;  // Setzt pt2 auf null.

// Eine Ausnahme bilden bool´s.
// Dies erlaubt es "null-pointer" zu testen: if(!ptr)
// Die Konsequenz ist jedoch, dass dem nullptr ein bool zugewiesen werden kann.
*pt = nullptr;  // Kompiliert auch, wenn '*pt' ein bool ist!

// '=' != '=' != '='!
// Ruft Foo::Foo(const Foo&) auf, oder den Kopierkonstruktor
Foo f2;
Foo f1 = f2;

// Ruft Foo::Foo(const Foo&) auf, aber kopiert lediglich den "Foo" Teil von
// "fooSub". Alle zusätzlichen Member werden verworfen. Diese eigenartige Verhalten
// wird auch "object slicing" genannt.
FooSub fooSub;
Foo f1 = fooSub;

// Ruft Foo::operator=(Foo&) oder eine andere Variante auf.
Foo f1;
f1 = f2;

///////////////////////////////////////
// Tuple (C++11 und höher)
///////////////////////////////////////

#include<tuple>

// Konzeptionell sind Tupel alten Datenstrukturen sehr ähnlich, allerdings haben diese keine
// bezeichneten Daten-Member, sondern werden durch die Reihenfolge angesprochen.

// Erstellen des Tupels und das Einfügen eines Werts.
auto first = make_tuple(10, 'A');
const int maxN = 1e9;
const int maxL = 15;
auto second = make_tuple(maxN, maxL);

// Ausgabe der Elemente des "first" Tuple.
cout << get<0>(first) << " " << get<1>(first) << "\n"; // Ausgabe : 10 A

// Ausgabe der Elemente des "second" Tuple.
cout << get<0>(second) << " " << get<1>(second) << "\n"; // Ausgabe: 1000000000 15

int first_int;
char first_char;
tie(first_int, first_char) = first;
cout << first_int << " " << first_char << "\n";  // Ausgabe : 10 A

// Tuple können auch wie folgt erzeugt werden:

tuple<int, char, double> third(11, 'A', 3.14141);
// tuple_size  gibt die Anzahl der Elemente in einem Tuple zurück.
// Als "constexpr".

cout << tuple_size<decltype(third)>::value << "\n"; // prints: 3

// tuple_cat fügt die Elemente eines Tupels aneinander (in der selben Reihenfolge).

auto concatenated_tuple = tuple_cat(first, second, third);
// concatenated_tuple wird zu = (10, 'A', 1e9, 15, 11, 'A', 3.14141)

cout << get<0>(concatenated_tuple) << "\n"; // Ausgabe: 10
cout << get<3>(concatenated_tuple) << "\n"; // Ausgabe: 15
cout << get<5>(concatenated_tuple) << "\n"; // Ausgabe: 'A'


///////////////////////////////////
// Logische- und Bitoperatoren
//////////////////////////////////

// Die meisten Operatoren in C++ entsprechen denen aus anderen Sprachen

// Logische Operatoren.
// C++ verwendet so genannte "Short-circuit" Evaluierung für Boolean-Ausdrücke.
// Das zweite Argument wird ausgeführt bzw. evaluiert, wenn das erste Argument genügt,
// um den Ausdruck zu bestimmen.

true && false // Führt **logisches und** aus.
true || false // Führt **logisches oder** aus.
! true        // Führt **logisches nicht** aus.

// Anstelle von Symbolen können auch Schlüsselwörter verwendet werden.
true and false // Führt **logisches und** aus.
true or false  // Führt **logisches oder** aus.
not true       // Führt **logisches nicht** aus.

// Bitoperationen

// **<<** Links-Shift
// **>>** Rechts-Shift

~4    // Führt bitweises nicht aus.
4 | 3 // Führt bitweises oder aus.
4 & 3 // Führt bitweises und aus.
4 ^ 3 // Führt bitweises xor aus.

// Gleichwertige Schlüsselwörter:
compl 4    // Führt bitweises nicht aus.
4 bitor 3  // Führt bitweises oder aus.
4 bitand 3 // Führt bitweises und aus.
4 xor 3    // Führt bitweises xor aus.
```

Weiterführende Literatur:

* Aktuelle Sprachen-Referenz [CPP Reference](http://cppreference.com/w/cpp).
* Zusätzliches: [CPlusPlus](http://cplusplus.com).
* Grundlagen Tutorial: [TheChernoProject - C++](https://www.youtube.com/playlist?list=PLlrATfBNZ98dudnM48yfGUldqGD0S4FFb).