c_plus_plus
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
c_plus_plus [2012/04/24 14:45] – skipidar | c_plus_plus [2020/12/27 20:35] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | == Namenskonventionen == | ||
+ | * *.h - Header File | ||
+ | * *.cc - Source File | ||
+ | * lib*.a - Library. When including the library, the " | ||
+ | * *.o - Object File. Precompiled, | ||
+ | ==== Basics ==== | ||
+ | |||
+ | C++ is a pass-by-value language. \\ | ||
+ | It is only possible to pass something (Object or primitive type) by reference, by explicitely expecting a reference. | ||
+ | |||
+ | <sxh cpp> | ||
+ | // | ||
+ | void swap(SomeType& | ||
+ | SomeType temp = arg1; | ||
+ | arg1 = arg2; | ||
+ | arg2 = temp; | ||
+ | } | ||
+ | |||
+ | ... | ||
+ | |||
+ | SomeType var1 = " | ||
+ | SomeType var2 = " | ||
+ | swap(var1, var2); // swaps their values! | ||
+ | // now var1 has value " | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | == Ausdruck und Anweisung == | ||
+ | {{ http:// | ||
+ | |||
+ | |||
+ | == Runden == | ||
+ | Beachte, dass FALSE in c als 0 behandelt wird. Somit wird im folgenden Vergleich der linke Teil zu 0 oder 1 ausgewertet und dann mit c verglichen | ||
+ | < | ||
+ | a<b<c -> | ||
+ | 0<c | ||
+ | 1<c | ||
+ | </ | ||
+ | |||
+ | == Typedefinition == | ||
+ | An additional variable type is defined with the syntax: typedef oldType newTapyAlias. E.g. an alias " | ||
+ | < | ||
+ | typedef int newVarTypeName | ||
+ | </ | ||
+ | |||
+ | == Konstante == | ||
+ | Eine Konstante welche in allen Scopes gültig ist kann definiert und wieder zurueck " | ||
+ | < | ||
+ | #define ConstantName constantValue | ||
+ | const ConstantName2 constantValue2 | ||
+ | |||
+ | #undef ConstantName | ||
+ | #undef ConstantName2 | ||
+ | </ | ||
+ | |||
+ | == Bitarithmetik == | ||
+ | Eine Konstante welche in allen Scopes gültig ist kann definiert und wieder zurueck " | ||
+ | < | ||
+ | a& | ||
+ | a|b OR | ||
+ | a~b XOR | ||
+ | ~a NOR | ||
+ | a<<b Linksshift | ||
+ | a>>b Rechtsshift | ||
+ | </ | ||
+ | |||
+ | == Gebrochenzahlige Zahlen == | ||
+ | Double oderlong double nutzen. Float braucht man nicht mehr. | ||
+ | Die Zahlen werden in der Regel abgerundet, somit schlägt der Vergleich fehl, wenn man folgendes macht: | ||
+ | < | ||
+ | 3 == pow ( pow(3,0.5) , 2 ) //bei den Berechnungen kann der linke Teil um eine winzige Zahl kleiner als 3 werden, somit wird er abgerundet und wird zu 2 | ||
+ | </ | ||
+ | |||
+ | |||
+ | === Speicherverwaltung === | ||
+ | |||
+ | C kann Speicherbereiche gezielt adressieren. Dazu wird der folgende Mechanismus benutzt: | ||
+ | |||
+ | == Wichtige unäre operatoren == | ||
+ | ***** ist der dereferenzeoperator. Er löst einen Pointer auf einen Objekt auf. | ||
+ | |||
+ | **&** ist der address-of operator. Er liefert die Adresse, an welcher der Objekt in der übergebenen Variable gespeichert ist.< | ||
+ | *Pointer = < | ||
+ | & | ||
+ | </ | ||
+ | |||
+ | \\ | ||
+ | \\ | ||
+ | |||
+ | **Vorweg: \\ | ||
+ | Referenzen sind statische Ersatznamen für eine Objekt. \\ | ||
+ | Pointer sind Objekte, die auf Speicherbereiche zeigen und mithilfe des dereferenzoperators (*) die Objekte in diesem Speicherbereich liefern koennen. \\ | ||
+ | Pointer können umgehangen werden** \\ | ||
+ | Ein tolle Erklärung zum Thema Pointer und Referenzen: \\ | ||
+ | [[http:// | ||
+ | |||
+ | == Referenz== | ||
+ | Eine Referenz sollte man als einen Ersatznamen eines Objektes sehen. | ||
+ | **JEDES** Auftreten einer Referenz wird vor dem Anfang **JEDER** Operation darauf zu deren Zielobjekt aufgelöst. Deswegen sind Referenz-Objekte selbst (nicht die Objekte für die sie als Ersatznamen dienen) - nach deren Erzeugung nicht mehr greifbar. | ||
+ | In C++ sind Referenzen typisiert, genau wie variablen. (In C gibt es Referenzen nicht als Typ, nur Pointer). | ||
+ | Referenztypen werden aus VariablenTypeNamen mit angehängeten & erzeugt. | ||
+ | Eine Referenz als Ersatznamen fuer A erstellt man wie folgt: | ||
+ | < | ||
+ | int A | ||
+ | int& referenzName = A; | ||
+ | </ | ||
+ | |||
+ | Eine Referenz muss sofort bei der Definition und für immer initialisiert werden. Die Referenz kann nicht auf ein anderes Ziel " | ||
+ | < | ||
+ | int& meineReferenz ; // compiler will complain: error: `meineReferenz' | ||
+ | </ | ||
+ | |||
+ | Trotz des Vorkommens von '&' | ||
+ | Deswegen wird der Referenz bei der Initialisierung - das Objekt selbst zugewiesen und nicht etwa dessen Adress im Speicher. | ||
+ | < | ||
+ | int var = 2; | ||
+ | int& meineReferenz = var; | ||
+ | </ | ||
+ | |||
+ | Der Typ der Referenz in der Objekorientierten Welt wird durch das anfügen des & zeichen RECHTS an dem Variablentyp gebildet. | ||
+ | < | ||
+ | typeof ( meineReferenz ) // int& | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | == Pointer == | ||
+ | Einen Pointer sollte man wie ein Objekt betrachten, welches auf eine Adresse zeigt, genau wie Referenzen. Ein Pointer ist nur eine Möglichkeit die im Speicher abgelegte Variable anders zu benennen. Im gegensatz zu den Referenzen können Pointer: | ||
+ | * Können Pointer auf ein anderes Ziel " | ||
+ | * Ein Pointer kann NULL sein. Referenzen sind sicherer, sie können nur ungültig werden, wenn der Speicherbereich auf den sie zeigen - ausserhalb der Reichweite oder fotmariert ist. | ||
+ | * Man kann die Adresse des Pointer-objektes rausfinden. Der-Referenz Objekt ist als Objekt nicht greifbar, er gibt bei jeder Erwähnung sein Ziel-Objekt aus. | ||
+ | * There' | ||
+ | |||
+ | Ein Pointer auf eine Variable sieht wie folgt aus: | ||
+ | < | ||
+ | *pointerName | ||
+ | </ | ||
+ | |||
+ | Initialisierung des Pointers sieht so aus: | ||
+ | < | ||
+ | int * number; | ||
+ | char * character; | ||
+ | float * greatnumber; | ||
+ | </ | ||
+ | |||
+ | Pointer werden zusammen mit dem " | ||
+ | Vor der Pointerdefinition muss der TypName der Variablen stehen, auf dessen Speicher der Pointer später zeigen soll. zB bei Integer siehts so aus: | ||
+ | < | ||
+ | double varA = 2; | ||
+ | double varB = 3; | ||
+ | double* pointerName; | ||
+ | pointername = &varA; //der Pointer " | ||
+ | echo (*pointername); | ||
+ | echo (pointername); | ||
+ | </ | ||
+ | |||
+ | Der Typ des Pointers in der Objekorientierten Welt wird durch das anfügen des Sterns RECHTS an dem Variablentyp gebildet: | ||
+ | < | ||
+ | typeof ( *pointerName ) // double* | ||
+ | typeof ( pointerName ) // int | ||
+ | </ | ||
+ | |||
+ | Es ist möglich einen Pointer mit einem unbestimmten Typ zu erstellen, indem man **void*** als typ nimmt. | ||
+ | bei solchen Zeigern hat der Kompiler aber keine Ahnung, was fuer eine Information im Speicher liegt. Sie muss gecastet werden. | ||
+ | <sxh cpp> | ||
+ | int a = 22222222; | ||
+ | void* test = &a; // compiler doesn' | ||
+ | int* b = reinterpret_cast< | ||
+ | std::cout << *b << endl; // gives 22222222 | ||
+ | </ | ||
+ | |||
+ | == Entsorgung des Pointers == | ||
+ | Weil mehrere Pointer auf eine Adresse zeigen können wird nach dem " | ||
+ | Es muss explizit gemacht werden durch | ||
+ | < | ||
+ | delete pointerName | ||
+ | </ | ||
+ | |||
+ | == Struct == | ||
+ | Ein struct ist eine möglichkeit mehrere Variablen in einem Objekt zu kapseln. \\ | ||
+ | Gekapselte Variablen dürfen nicht initiiert worden sein. | ||
+ | <sxh cpp> | ||
+ | struct Computer{ | ||
+ | int ram; | ||
+ | int mhz; | ||
+ | int terrabyte; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Typedef can be used, to define a struct as a new encapsulation object. | ||
+ | <sxh cpp> | ||
+ | typedef struct{ | ||
+ | int x; | ||
+ | int y; | ||
+ | } Point; | ||
+ | |||
+ | //after that you can use a Point construct. | ||
+ | |||
+ | Point a; | ||
+ | a.x = x; | ||
+ | a.y = y; | ||
+ | return a; | ||
+ | </ | ||
+ | |||
+ | == Union == | ||
+ | Wie **struct**, nur teilen sich die, im union definierten variablen, den Speicherplatz. | ||
+ | |||
+ | |||
+ | |||
+ | == Arrays == | ||
+ | Die Arrays in C++ sind als Pointer implementiert. | ||
+ | Der Name des Arrays zeigt auf eine Adresse im Speicher, wo das erste Array-Element gespeichert ist. | ||
+ | Um das nächste Element aus dem Array zu holen - bewegt das System den Zeiger um \\sizeof (TYPE)\\ weiter im Speicher. | ||
+ | | ||
+ | Da Arrays als Pointer implementiert sind - kann ein Array auf zwei wegen definiert werden: | ||
+ | - Indem der ganze Speicher dem Array sofort bei der Definition zugewiesen wird. <sxh cpp> | ||
+ | |||
+ | int arrayName[] = {1,2,3,4,5} //das Array mit 5 Elementen | ||
+ | int arrayName[5] = {1, | ||
+ | </ | ||
+ | - Indem der nötige Speicher erst bei der späteren Initiierung vom freispeicher geholt und dem Array zugewiesen wird. <sxh cpp> | ||
+ | |||
+ | int* arrayName; | ||
+ | arrayName = new int[5]; //erst jetzt wird der nötige Speicher vom Freispeicher abgeschnitten und dem Array zugewiesen. | ||
+ | </ | ||
+ | |||
+ | |||
+ | == Gefährliche Syntax == | ||
+ | <sxh cpp> | ||
+ | // | ||
+ | //Pointer depth 1 | ||
+ | int marr[] = {1, | ||
+ | int* pmarr | ||
+ | |||
+ | int* | ||
+ | |||
+ | //Pointer depth 2 | ||
+ | int** ppmarr | ||
+ | |||
+ | //TYPES | ||
+ | //array and pointer are different, which can be seen by checking their types | ||
+ | std::cout << "type of marr is: " << typeid(marr).name() | ||
+ | std::cout << "type of &marr is: " << typeid(& | ||
+ | |||
+ | std::cout << "type of pmarr is: " << typeid(pmarr).name() | ||
+ | std::cout << "type of &pmarr is: " << typeid(& | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | == Funktionen == | ||
+ | Die Funktionen werden, wie in Java, definiert. 2 Unterschiede gibt es: | ||
+ | - Parameter der Funktionen können mit default werten initiiert werden. Bei der Nutzung der Funktionen können diese Parameter dann ausgelasssen werden.< | ||
+ | |||
+ | void Func(int one, int two, int three){ | ||
+ | | ||
+ | } | ||
+ | void Func(one = 1, two=2, three=3); | ||
+ | Func(10, | ||
+ | Func(10, | ||
+ | Func(10); | ||
+ | </ | ||
+ | |||
+ | **ACHTUNG: | ||
+ | wird ein Array als Funktions-Parameter erwartet, so wird auch ein Pointer an seiner Stelle angenommen, weil Arrays - als Pointer implementiert werden. | ||
+ | <sxh cpp> | ||
+ | void Func(int[] mArray){ | ||
+ | ... | ||
+ | } | ||
+ | int[] arrOne = {1,2,3} | ||
+ | Func(arrOne); | ||
+ | |||
+ | int* arrPointer; | ||
+ | Func(arrPointer); | ||
+ | </ | ||
+ | Dabei muss man zwei sachen beachen: | ||
+ | - der Pointer muss mit **delete** explizit vernichtet werden, um den SPeicher frei zu geben, | ||
+ | - die Arrays werden "by reference" | ||
+ | |||
+ | |||
+ | |||
+ | **ACHTUNG2: | ||
+ | Der Operator **void** als Funktionsparameter bedeutet, dass die Funktion keine Parameter annimmt. \\ | ||
+ | Kein Parameter bei einer Funktion bedeutet, dass die Funktion eine beliebige Anzahl von Parametern annimmt. \\ | ||
+ | <sxh cpp> | ||
+ | void noParamFunc(void){} // | ||
+ | void anyParamFunc(){} // anyParamFunc(1) anyParamFunc(" | ||
+ | </ | ||
+ | |||
+ | == Operatoren == | ||
+ | Operatoren sind Funtionen, die nicht in der // | ||
+ | <sxh cpp> | ||
+ | // | ||
+ | () [] -> . | ||
+ | ! ~ ++ -- + - ( type ) * & sizeof new delete | ||
+ | ->* .* | ||
+ | * / % | ||
+ | + - | ||
+ | << >> | ||
+ | < <= > >= | ||
+ | == != | ||
+ | & | ||
+ | ^ | ||
+ | | | ||
+ | && | ||
+ | || | ||
+ | ?: right to left | ||
+ | = += -= *= /= %= <<= >>= &= ^= |= throw | ||
+ | ?: (C++, third operand ) | ||
+ | , | ||
+ | </ | ||
+ | |||
+ | |||
+ | Operatoren können überladen werden. Das heisst den Operatoren kann man beibringen, wie man mit neuen Objekttypen umgeht. \\ | ||
+ | Es können keine neuen Operatoren definiert werden wie z.B. ein Exponential-Operator " | ||
+ | <sxh cpp> | ||
+ | //so wird ein operator X überladen an dem k Zahlen beteiligt sind | ||
+ | RückgabeTyp operatorX(Def1, | ||
+ | |||
+ | //so wird ein operator + überladen fuer den eigens definierten Typ namens " | ||
+ | complex operator+(complex& | ||
+ | { | ||
+ | | ||
+ | ... | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | == Makefile == | ||
+ | Makefiles ermöglichen die Automatisierung des Kompillier-Prozesses von mehreren Dateien inkl. der Auflösung von Abhängigkeiten. \\ | ||
+ | In Makefiles definiert man Blockweise Dateien und Abhängigkeit ( Bibliotheken, | ||
+ | Zusätzlich werden die Befehle aufgeführt, | ||
+ | |||
+ | Syntax: | ||
+ | |||
+ | <sxh cpp> | ||
+ | //Makros | ||
+ | makro1 = . | ||
+ | makro2 = $(makro1)/ | ||
+ | makro3 = $(makro1)/ | ||
+ | makro4 = $(makro1)/ | ||
+ | makro5 = $(makro1)/ | ||
+ | makro6 = $(makro1)/ | ||
+ | |||
+ | MAKRO_BINFILES = $(makro3)/ | ||
+ | MAKRO_LIBFILES = $(makro3)/ | ||
+ | C++ = / | ||
+ | MAKRO_BIND | ||
+ | |||
+ | |||
+ | //block1 | ||
+ | $(makro1)/ | ||
+ | | ||
+ | //block2 | ||
+ | $(makro2)/ | ||
+ | .... | ||
+ | |||
+ | </ | ||
+ | |||
+ | Das Makro **$@** gibt das aktuelle Ziel aus. \\ | ||
+ | Das Makro **$?** gibt alle Abhängigkeiten des aktuellen Blockes aus, dessen Zeitstempel aelter als das Zeitstempel des Zeils ist. | ||
+ | |||
+ | |||
+ | |||
+ | == Casting == | ||
+ | |||
+ | * **dynamic_cast** - safe. Compile time check. Returns null when cast fails - \\ because there are no reflections and expecially no // | ||
+ | class Bla{}; | ||
+ | class Subbla : Bla{}; | ||
+ | |||
+ | Bla varBla | ||
+ | SubBla varSubBla = new Subbla; | ||
+ | |||
+ | Bla* pBla = dynamic_cast< | ||
+ | Bla* pSubBla = dynamic_cast< | ||
+ | |||
+ | </ | ||
+ | * **static_cast** - Unsafe. Runtime check - \\ is used to downcast classes from base to the child. Throws Errror at runtime if classes uncompatible. <sxh cpp> | ||
+ | double d=3.14159265; | ||
+ | int i = static_cast< | ||
+ | * **implicite cast** - dangerous but powerfull. \\ Tries every other way to cast out. <sxh cpp> | ||
+ | double d=3.14159265; | ||
+ | int i = (int)d; </ | ||
+ | |||
+ | More information about casting here: | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== Klassen ==== | ||
+ | Die Klassen können mithilfe von zweien Stichwörtern deklariert werden: | ||
+ | * class | ||
+ | * struct | ||
+ | Der Unterschied besteht darin, dass man im **class** irgendwo ein Keyword namens **public** nutzen kann. Alles was danach in einer Klasse auftritt - ist von außen erreichbar. Der Rest der Klasse, also alles vor public, ist private. \\ | ||
+ | |||
+ | Innerhalb eines **struct** ist alles als public deklariert. | ||
+ | <sxh cpp> | ||
+ | class person | ||
+ | { | ||
+ | public: | ||
+ | string name; | ||
+ | int age; | ||
+ | }; | ||
+ | |||
+ | struct person | ||
+ | { | ||
+ | string name; | ||
+ | int age; | ||
+ | |||
+ | }; | ||
+ | </ | ||
+ | |||
+ | |||
+ | Die Funktionen können einer Klasse später, außerhalb der Klasse selbst zugewiesen werden. | ||
+ | <sxh cpp> | ||
+ | class rechner | ||
+ | { | ||
+ | // ... | ||
+ | | ||
+ | void leerfunk(int a, int b, int c = 0, int d = 0); | ||
+ | }; | ||
+ | |||
+ | void rechner:: | ||
+ | { | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | == Instantiierung == | ||
+ | **ACHTUNG: ** der Operator **new** hat eine andere Bedeutung in C++ als in Java. | ||
+ | <sxh cpp> | ||
+ | // | ||
+ | Bla varBla | ||
+ | Bla* varBlaPointer = new Bla(); // saying "new Bla" gives a pointer | ||
+ | </ | ||
+ | |||
+ | |||
+ | == Sichtbarkeit == | ||
+ | **Methoden und Felder** \\ | ||
+ | Wie in Java kann man die Sichtbarkeit der Methoden und Felder einschränken. \\ | ||
+ | Die syntax ist allerdings eine andere. Die Klasse wird in Bereiche unterteilt. Abhängig davon in welchem Bereich sich etwas befindet - aendert sich die sichtbarkeit. | ||
+ | <sxh cpp> | ||
+ | class Bla{ | ||
+ | // | ||
+ | | ||
+ | int publVar; | ||
+ | void publFunc(); | ||
+ | |||
+ | // | ||
+ | | ||
+ | int protVar; | ||
+ | void protFunc(); | ||
+ | |||
+ | //nur in klasse. Konvention: _ bei privatem voranstellen. | ||
+ | | ||
+ | int _privVar; | ||
+ | void _privFunc(); | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | **Klassen** \\ | ||
+ | Bei Klassen kann man in C++ nicht einfach die Sichtbarkeit setzen. \\ | ||
+ | Nur, wenn eine Klasse von einer anderen erbt - kann man das. \\ | ||
+ | Das ist auf die Mehrfachvererbung zurück zu führen - bei der Erbung von Klasse A sind A's Eigenschaften privat. Bei der Erbung von Klasse B sind B's Eigenschaften public. | ||
+ | |||
+ | <sxh cpp> | ||
+ | class A | ||
+ | { | ||
+ | public: | ||
+ | int x; | ||
+ | protected: | ||
+ | int y; | ||
+ | private: | ||
+ | int z; | ||
+ | }; | ||
+ | |||
+ | class B : public A | ||
+ | { | ||
+ | // x is public | ||
+ | // y is protected | ||
+ | // z is private and is not accessible from B | ||
+ | }; | ||
+ | |||
+ | class C : protected A | ||
+ | { | ||
+ | // x is protected | ||
+ | // y is protected | ||
+ | // z is private and is not accessible from C | ||
+ | }; | ||
+ | |||
+ | class D : private A | ||
+ | { | ||
+ | // x is private and not accessible from D | ||
+ | // y is private and not accessible from D | ||
+ | // z is private and not accessible from D | ||
+ | }; | ||
+ | |||
+ | //on default the inheritance is private | ||
+ | class E : A | ||
+ | { | ||
+ | // x is private and not accessible from D | ||
+ | // y is private and not accessible from D | ||
+ | // z is private and not accessible from D | ||
+ | }; | ||
+ | </ | ||
+ | |||
+ | |||
+ | == this == | ||
+ | Innerhalb von C++ Objekten gibt es einen Pointer namens **this**, genau wie in java. | ||
+ | |||
+ | |||
+ | ==Destruktoren und Konstruktoren== | ||
+ | |||
+ | Destruktoren sind Funktionen mit demselben Namen wie deren Klasse. Diese Funktionen haben " | ||
+ | |||
+ | Destruktoren sind Funktionen mit demselben Namen wie deren Klasse. Diese Funktionen haben "" | ||
+ | <sxh cpp> | ||
+ | class MyExampleClass{ | ||
+ | |||
+ | public: | ||
+ | // | ||
+ | MyExampleClass(){ | ||
+ | } | ||
+ | MyExampleClass(int i){ | ||
+ | } | ||
+ | |||
+ | // | ||
+ | ~Klassenname(); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | === Syntax details === | ||
+ | Es gibt eine Abkürzung, wenn man Pointer benutzt, um Funktionen eines Objektes auf zu rufen. | ||
+ | <sxh cpp> | ||
+ | MyNamespace:: | ||
+ | MyNamespace:: | ||
+ | |||
+ | // . is a " | ||
+ | mc.saySomething(); | ||
+ | |||
+ | // -> is a " | ||
+ | (*pmc).saySomething(); | ||
+ | pmc-> | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==== Kontrollstrukturen ==== | ||
+ | == if == | ||
+ | Wird ausgefuehrt, | ||
+ | |||
+ | <sxh cpp> | ||
+ | if(42){ | ||
+ | Expression | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Performance ==== | ||
+ | |||
+ | == Inline == | ||
+ | Funktion kann als " | ||
+ | Mithilfe der inline Funktionen lagert man knifflige Fragmente in eigene Funktionen aus. \\ | ||
+ | Definiert man zu viele, nicht triviale Funktionen als " | ||
+ | <sxh cpp> | ||
+ | inline void myFunc(int a, int b){ | ||
+ | return a+b; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | ==== Wie sieht die Struktur eines C++ Programmes aus ==== | ||
+ | Was muss man kennen, um C++ Programme erfolgreich zu schreiben? | ||
+ | |||
+ | ==Mehrere Dateien== | ||
+ | Ein C++ Programm kann aus mehreren Dateien bestehen. Bei der Kompilierung müssen die in einer Datei genutzten Variablen und Funktionen entweder in dieser Datei | ||
+ | - Definiert (und initialisiert) worden sein < | ||
+ | int myFunction(int a, int b){...} | ||
+ | </ | ||
+ | - Oder zu mindestens **deklariert**, | ||
+ | int myFunction(int a, int b); | ||
+ | </ | ||
+ | |||
+ | ==Header Dateien *.h == | ||
+ | // | ||
+ | Um die Konsistenz-Probleme zu vermeiden und Funktionen und Variablen zentral zu verwalten sieht die Nutzung einer Funktion oder Variablen und multiplen Dateien so aus: **definiert** und **initialisiert** wird die Variable/ | ||
+ | |||
+ | // | ||
+ | Will man diese Funktionen/ | ||
+ | Deswegen **deklariert** man diese Funktion/ | ||
+ | |||
+ | == Manuelle Auflösung der Abhängigkeiten == | ||
+ | C++ kümmert sich nicht selbst, um die Auflösung der Abhängigkeiten der Bibliotheken voneinander, | ||
+ | Darum muss sich der Nutzer manuell Kümmern. | ||
+ | |||
+ | //Split der Definitionen in verschiedene Dateien // \\ | ||
+ | Um Probleme mit der transitiven Einbindung einer Header Datei mehrmals zu vermeiden - definiert man eine Indikator-Variable beim Einbinden jeder Header Datei. | ||
+ | Beim Einbinden prüft man dann, ob die Indikator-Variable bereits definiert ist. Falls nein - wird die header Datei eingebunden. | ||
+ | <sxh cpp> | ||
+ | #ifdef IndikatorVar | ||
+ | #define IndikatorVar | ||
+ | |||
+ | #include HeaderFile | ||
+ | |||
+ | #endif | ||
+ | </ | ||
+ | |||
+ | |||
+ | // | ||
+ | Wenn eine Bibliothek von anderen abhängt - müssen die Abhängigkeiten beim Kompilieren zuerst eingebunden werden. | ||
+ | Wenn 2 Bibliotheken voneinander abhängen, dann muss mindestens eine Bibliothek zwei mal erwähnt werden: | ||
+ | < | ||
+ | cc -lBasisLibName1 -lBasisLibName2 -lBasisLibName1 | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== Praxis ==== | ||
+ | Als IDE nutze Eclipse für C++ Developer. | ||
+ | |||
+ | == Code Struktur == | ||
+ | Als Beispiel für die Code Struktur wird das VLC Projekt betrachtet: | ||
+ | * Im **src** für jede zu implementierende Funktionalität(Netzwerk, | ||
+ | * In jedem Unterordner liegen alle Source (*.c *.cpp) und alle Header Dateien (*.h) zusammen. | ||
+ | |||
+ | So bleiben die Hierarchien flach und übersichtlich. | ||
+ | |||
+ | {{http:// | ||
+ | |||
+ | |||
+ | == Erstellung eines Projektes == | ||
+ | * Jede neue Source Datei wird zusammen mit einem Header erstellt. | ||
+ | * Als erstes deklariert man neue Funktionen in der **header Datei** | ||
+ | * Danach wird lässt man Eclipse den Rumpf dieser Funktionen automatisch erstellen, über [Source > Implement Method] | ||
+ | |||
+ | {{http:// | ||
+ | |||
+ | == include == | ||
+ | Nutze die < | ||
+ | Bei dieser Notation durchsucht Eclipse auch die Unterverzeichnisse des aktuellen Projektes und schlägt vor die eigenen Header zu importieren wenn man **ALT + Leertaste ** drueckt | ||
+ | |||
+ | {{http:// | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== Eclipse ==== | ||
+ | Source lookup problem, which occurs when Eclipse is used with cygwin and when Eclipse searches for source files on the "/ | ||
+ | This problem can be solved, by using Eclipse' | ||
+ | |** Setting: | ||
+ | |** Menu path: | ||
+ | |** Value: | ||
+ | |||
+ | {{youtube> | ||
+ | |||
+ | |||
+ | |||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | |||
+ | ==== Summary ==== | ||
+ | |||
+ | ==Eine Liste der wichtigen Momente, um Referenzen und Pointer zu verstehen: | ||
+ | * Referenzen haben einen festen Typ, abhängig davon was sie referenzieren. Der Referenztyp wird gebildet als < | ||
+ | int& | ||
+ | float& | ||
+ | double& </ | ||
+ | * Trotz des Vorkommens vom '&' | ||
+ | * Pointer haben einen festen Typ, abhängig davon was sie referenzieren. Der Referenztyp wird gebildet als < | ||
+ | int* | ||
+ | float* | ||
+ | double* </ | ||
+ | * Pointer selbst speichern Adressen, die mit dem " | ||
+ | p = &var </ | ||
+ | * Pointer können mit dem unären Dereferenzoperator ' | ||
+ | int* p; | ||
+ | p = & | ||
+ | echo (*p) \\2 </ | ||
+ | * Referenzen sind für immer, können nicht auf andere Objekte " | ||
+ | * Pointer können " | ||
+ | * Pointer müssen manuell entsorgt werden durch " | ||
+ | |||
+ | ^Konzept ^Bezeichnung ^Erklärung ^Initiierung ^ | ||
+ | | TYPE& refName = varName | Referenz | Ist ein alias für eine Variable. Wird einmal und fuer immer initiiert. | Wird mit Variablennamen initiiert, weil Referenz immer genau dasselbe bedeutet, wie dessen Ziel. Zusaetzlich ist eine explizite Referenz als Methodenparameter - die einzige Möglichkeit etwas "by reference" | ||
+ | | & | ||
+ | | TYPE* pointerName | Pointer | Ist ein pointer auf **die Adresse der Variablen** | Wird mit **der Adresse** der Variablen initiiert. | | ||
+ | | *pointerName | Dereferenz Operator | wenn man * vor einem Pointernamen setzt - dann gibt der Ausdruck **den Wert** der Variablen zurueck, die im Speicher an der Stelle liegt, auf welche der Pointer zeigt. | | | ||
+ | |||
+ | * Everything is passed by value, even the objects (Except when passing by reference is explicitely used) <sxh cpp> | ||
+ | //objects are passed by value on default (not like in java) | ||
+ | void swapObj(MyNamespace:: | ||
+ | // | ||
+ | void swapRefObj(MyNamespace:: | ||
+ | </ | ||
+ | * The functions can not be overloaded by references. References are allways replaced by their aim, so such an overload is ambigous | ||
+ | * The function, which needs a reference can be started with a normal value instead of the reference, because there is no diffrerence between reference and their aim. | ||
+ | * The operator **new** is not used, like in java. Using new returns a **pointer** to a new object. <sxh cpp> | ||
+ | MyType | ||
+ | MyType* pvar = new MyType(); //A pointer to a new instance returned, because new was used. | ||
+ | </ |