== Namenskonventionen ==
* *.h - Header File
* *.cc - Source File
* lib*.a - Library. When including the library, the "lib" prefix is not mentioned.
* *.o - Object File. Precompiled, not executable code (no main function)
==== 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.
//SomeType& is a reference Type
void swap(SomeType& arg1, Sometype& arg2) {
SomeType temp = arg1;
arg1 = arg2;
arg2 = temp;
}
...
SomeType var1 = "A";
SomeType var2 = "B";
swap(var1, var2); // swaps their values!
// now var1 has value "B" and var2 has value "A"
== Ausdruck und Anweisung ==
{{ http://i42.tinypic.com/jr2ltt.png }}
== 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
0
== Typedefinition ==
An additional variable type is defined with the syntax: typedef oldType newTapyAlias. E.g. an alias "newVarTypeName" for int is defined as following:
typedef int newVarTypeName
== Konstante ==
Eine Konstante welche in allen Scopes gültig ist kann definiert und wieder zurueck "undefiniert" werden:
#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 "undefiniert" werden:
a&b AND
a|b OR
a~b XOR
~a NOR
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 = //in Java ist der Punkt-Operator der äquivalent zum Stern operator. Objektname.var löst "Objektname" zu einem Objekt auf.
&Variable =
\\
\\
**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://www.cplusplus.com/doc/tutorial/pointers/ | http://www.cplusplus.com/doc/tutorial/pointers/]]
== 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 "umgehangen" werden. Pointer können "umgehangen" werden.
int& meineReferenz ; // compiler will complain: error: `meineReferenz' declared as reference but not initialized
Trotz des Vorkommens von '&' Zeichen und obwohl die Referenzen als Pointer implementiert sind - hat das Konzept der Referenz nichts mit dem Speicher zu tun.
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 "umgehangen werden" - Referenzen werden bei deren erstellung ein für alle mal initialisiert. Somit sind referenzen - statische Pointer
* 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's no "reference arithmetics" (but you can take the address of an object pointed by a reference and do pointer arithmetics on it as in &obj + 5).
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 "adress-of" Operator benutzt.
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; //neuer Pointer auf int Variablen namens "pointerName" definiert
pointername = &varA; //der Pointer "ponterName" zeigt nun auf die Adresse der Variablen. Er kann, zusammen mit dem Dereferenzoperator den Inhalt von varA liefern
echo (*pointername); //liefert 2
echo (pointername); //liefert die MEMORY-ADRESSE der Variablen varA. Die Adresse ist ein int Wert.
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.
int a = 22222222;
void* test = &a; // compiler doesn't know, that test points to int
int* b = reinterpret_cast(test); // reinterpret the pointer test as pointer to int
std::cout << *b << endl; // gives 22222222
== Entsorgung des Pointers ==
Weil mehrere Pointer auf eine Adresse zeigen können wird nach dem "Umhängen des Pointers" auf andere Adresse der Speicher nicht freigegeben.
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.
struct Computer{
int ram;
int mhz;
int terrabyte;
}
Typedef can be used, to define a struct as a new encapsulation object.
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.
int arrayName[] = {1,2,3,4,5} //das Array mit 5 Elementen
int arrayName[5] = {1,2,3} //das Array mit 5 Elementen, wovon 3 initialisiert werden. Dem Array wird trotzdem sofort der ganze Speicher 5* sizeof(int) zugewiesen.
- Indem der nötige Speicher erst bei der späteren Initiierung vom freispeicher geholt und dem Array zugewiesen wird.
int* arrayName; //der Array wird als Pointer initiiert. Nutze das Wissen ueber die Implementierung des Arrays als Pointer aus.
arrayName = new int[5]; //erst jetzt wird der nötige Speicher vom Freispeicher abgeschnitten und dem Array zugewiesen.
== Gefährliche Syntax ==
//ATTENTION:
//Pointer depth 1
int marr[] = {1,13,25,37,45,56}; // array is implemented as a Pointer TO THE FIRST ARRAY ELEMENT
int* pmarr = marr; // don't use & for assignment, because same pointer depth. Assigning Pointer = Pointer makes them equal. So pmarr points to the first ArrayElement.
int* point = (marr + 1); // ATTENTION: moves the array-pointer in memory, but by sizeof(TYPE) and not by 1 byte. The steps are equal to the type of the array-elements (here sizeof(int))
//Pointer depth 2
int** ppmarr = &pmarr; // use & because going one level deeper. So use the address of the pointer.
//TYPES
//array and pointer are different, which can be seen by checking their types
std::cout << "type of marr is: " << typeid(marr).name() << std::endl; // int* so marr gives a pointer to the first array element
std::cout << "type of &marr is: " << typeid(&marr).name() << std::endl; // int (*)[6] so &marr gives a pointer to the whole array
std::cout << "type of pmarr is: " << typeid(pmarr).name() << std::endl; // int* so pmarr gives a pointer to the first array element
std::cout << "type of &pmarr is: " << typeid(&pmarr).name() << std::endl; // int** so &pmarr gives a pointer to to pointer to the first array elelemt. Because & gets us one level deeper.
== 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){
return one+two+three;
}
void Func(one = 1, two=2, three=3);
Func(10,20,30); //return 10+20+30=60
Func(10,20); //dont define the last param return 10+20+3=33
Func(10); //dont define the last 2 params return 10+2+3=15
**ACHTUNG:** \\
wird ein Array als Funktions-Parameter erwartet, so wird auch ein Pointer an seiner Stelle angenommen, weil Arrays - als Pointer implementiert werden.
void Func(int[] mArray){
...
}
int[] arrOne = {1,2,3}
Func(arrOne); //valid call, expected behaviour
int* arrPointer;
Func(arrPointer); //valid call, unexpected behaviour
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" übergeben, wenn man mit dem Array-Funktionsparameter arbeitet - greift man auf denselben Speicherbereich zu, der bei der Arrayinitiierung dem Array zugewisen wurde.
**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. \\
void noParamFunc(void){} //noParamsFunc(1) is illegal
void anyParamFunc(){} // anyParamFunc(1) anyParamFunc("bla",21) is legal
== Operatoren ==
Operatoren sind Funtionen, die nicht in der //function()// Notation aufgerufen werden, sondern in der Infix, Postfix etc. Notation.
//operatoren
() [] -> .
! ~ ++ -- + - ( 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 "\*\*" oder ähnliches.
//so wird ein operator X überladen an dem k Zahlen beteiligt sind
RückgabeTyp operatorX(Def1, Def2, ..., Defk){}
//so wird ein operator + überladen fuer den eigens definierten Typ namens "complex"
complex operator+(complex& lhs, complex& rhs)
{
complex Tmp;
...
return Tmp;
}
== 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, Header Dateien ). \\
Zusätzlich werden die Befehle aufgeführt, die ausgeführt werden sollen, um die Abhängigkeiten aufzulösen.
Syntax:
//Makros
makro1 = .
makro2 = $(makro1)/code
makro3 = $(makro1)/sources
makro4 = $(makro1)/include
makro5 = $(makro1)/routines
makro6 = $(makro1)/lib
MAKRO_BINFILES = $(makro3)/ObjectFile.o
MAKRO_LIBFILES = $(makro3)/Y1.o $(makro3)/Y2.o $(makro3)/Y3.o
C++ = /usr/local/bin/gcc
MAKRO_BIND = $(C++) $(LIBDIRS)
//block1
$(makro1)/BinaryZiel : $(MAKRO_BINFILES) $makro2/dependecy1.a
$(MAKRO_BIND) -o $@ $(MAKRO_BINFILES) $(MAKRO_LIBFILES)
//block2
$(makro2)/dependecy1: $(MAKRO_LIBFILES)
....
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 //instanceof// in C++ this function is used to upcast a class to it's base class. This ist important:
class Bla{};
class Subbla : Bla{};
Bla varBla = new Bla;
SubBla varSubBla = new Subbla;
Bla* pBla = dynamic_cast(varSubBla); //success. pBla has a SubBla in it
Bla* pSubBla = dynamic_cast(varBla); //fail at runtime.
* **static_cast** - Unsafe. Runtime check - \\ is used to downcast classes from base to the child. Throws Errror at runtime if classes uncompatible.
double d=3.14159265;
int i = static_cast(d);
* **implicite cast** - dangerous but powerfull. \\ Tries every other way to cast out.
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.
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.
class rechner
{
// ...
public:
void leerfunk(int a, int b, int c = 0, int d = 0);
};
void rechner::leerfunk(int a, int b, int c, int d)
{
return a + b + c + d;
}
== Instantiierung ==
**ACHTUNG: ** der Operator **new** hat eine andere Bedeutung in C++ als in Java.
//ATTENTION: using "new" for instantiation returns a Pointer in C++
Bla varBla = Bla(); // no "new" keyword. Bla instantiated.
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.
class Bla{
//ueberall
public:
int publVar;
void publFunc();
//klasse und unterklassen
protected:
int protVar;
void protFunc();
//nur in klasse. Konvention: _ bei privatem voranstellen.
private:
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.
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 "~" als Rückgabetyp. Ein Destruktor wird vor der Zerstörung des Objektes automatisch aufgerufen.
Destruktoren sind Funktionen mit demselben Namen wie deren Klasse. Diese Funktionen haben "" als Rückgabetyp.
class MyExampleClass{
public:
//Constructor
MyExampleClass(){
}
MyExampleClass(int i){
}
//destruktor
~Klassenname();
}
=== Syntax details ===
Es gibt eine Abkürzung, wenn man Pointer benutzt, um Funktionen eines Objektes auf zu rufen.
MyNamespace::MyClass mc = MyNamespace::MyClass(42);
MyNamespace::MyClass* pmc = &mc;
// . is a "sending message" operator
mc.saySomething();
// -> is a "dereference AND sending message" operator
(*pmc).saySomething(); //calls saySomething()
pmc->saySomething(); //calls saySomething() too
==== Kontrollstrukturen ====
== if ==
Wird ausgefuehrt, wenn der Wert in Klammern != 0 ist.
if(42){
Expression
}
==== Performance ====
== Inline ==
Funktion kann als "inline" deklariert werden. Dadurch wird der code **eventuell, wenn der compiler sich dazu entscheidet** anders compiliert und die inline Funktion effektiver aufgerufen. \\
Mithilfe der inline Funktionen lagert man knifflige Fragmente in eigene Funktionen aus. \\
Definiert man zu viele, nicht triviale Funktionen als "inline" - geht die compiler Optimierung kaputt.
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 varName = 2;
int myFunction(int a, int b){...}
- Oder zu mindestens **deklariert**, falls die Definition in einer anderen Datei bereits erledigt wurde extern int varName;
int myFunction(int a, int b);
==Header Dateien *.h ==
//Definition// \\
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/Funktion in einer der *.cc Dateien.
//Deklaration// \\
Will man diese Funktionen/Variablen in multiplen anderen Dateien nutzen, so müsste man diese theoretisch in allen diesen Dateien **deklarieren**, was zu Konsistenz-Problemen führen kann, wenn sich der Name der Variablen/Funktion ändern sollte.
Deswegen **deklariert** man diese Funktion/Variable einmal in einer **header Datei** und bindet diese Datei überall ein, wo man die Deklarationen braucht.
== Manuelle Auflösung der Abhängigkeiten ==
C++ kümmert sich nicht selbst, um die Auflösung der Abhängigkeiten der Bibliotheken voneinander, der Dateien mit Variablen und Funktionen-definitionen 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.
#ifdef IndikatorVar
#define IndikatorVar
#include HeaderFile
#endif
//Abhängigkeiten der Bibliotheken voneinander// \\
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, Audio, Video...) werden Unterordner erstellt.
* In jedem Unterordner liegen alle Source (*.c *.cpp) und alle Header Dateien (*.h) zusammen.
So bleiben die Hierarchien flach und übersichtlich.
{{http://i42.tinypic.com/mbmr91.png}}
== 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://i42.tinypic.com/2cqles5.png}}
== include ==
Nutze die include "name.h"
Notation, also die "name.h" anstatt \\
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://i40.tinypic.com/k4xjpz.png}}
==== Eclipse ====
Source lookup problem, which occurs when Eclipse is used with cygwin and when Eclipse searches for source files on the "/cygdrive/.." paths. \\
This problem can be solved, by using Eclipse's **"path mapping"**
|** Setting:** | path mapping |
|** Menu path:** | Window> Preferences> C++ > Debug> Source Lookup Path> Add > Path mapping |
|** Value:** | /cygdrive/d | D:\ |
{{youtube>KCq2yWDJNLM}}
\\
\\
\\
\\
\\
\\
\\
\\
\\
\\
\\
\\
\\
\\
\\
\\
==== 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 'ZielObjektTyp'+'&'
int&
float&
double&
* Trotz des Vorkommens vom '&' Zeichen im Typ der Referenzen sind Referenzen - Ersatznamen für Objekte. Deswegen werden Objekte den Referenzen zugewiesen und nicht etwa die Adressen der Objekte. Der unäre "adress-of" Operator hat nichts mit den Referenzen zu tun.
* Pointer haben einen festen Typ, abhängig davon was sie referenzieren. Der Referenztyp wird gebildet als 'ZielObjektTyp'+'*'
int*
float*
double*
* Pointer selbst speichern Adressen, die mit dem "adress-of" Operator (&) vor der Objekt-Variablen abgefragt werden kann int* p;
p = &var
* Pointer können mit dem unären Dereferenzoperator '*' aufgelöst werden. Mit einem '*' vor der Pointer-Variablen wird der Inhalt an der Adresse, die im Pointer gespeichert ist, abgefragt.int var = 2
int* p;
p = &var
echo (*p) \\2
* Referenzen sind für immer, können nicht auf andere Objekte "umgehangen" werden
* Pointer können "umgehangen" werden
* Pointer müssen manuell entsorgt werden durch "delete PointerName"
^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" zu übergeben |
| &varName | Adress-off Operator | wenn man & vor einem variablennamen setzt - dann gibt der Ausdruck die Adresse der Variablen im Speicher zurück | |
| 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)
//objects are passed by value on default (not like in java)
void swapObj(MyNamespace::MyClass a, MyNamespace::MyClass b);
//explicitely passing by reference
void swapRefObj(MyNamespace::MyClass& a, MyNamespace::MyClass& b);
* 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.
MyType var = MyType(); //no new used. Instance of the object returned.
MyType* pvar = new MyType(); //A pointer to a new instance returned, because new was used.