[[:improve]]
CPlusPlus oder auch (C++) ist eine objektorientierte Programmiersprache. Siehe auch [[coding:c|C]]/[[coding:csharp|C#]].
[[https://en.cppreference.com/w/cpp/keyword|Cpp reference]]
* explicit - makes a conversion constructor to non-conversion constructor. [[https://weblogs.asp.net/kennykerr/Explicit-Constructors|A good Write up]]
* virtual - override class method
* mutable - when you have a const class but want to change parts of it.
=====Classes=====
Klassen mit mindestens einer "virtual" Funktion nennt man Polymorphe Klassen.
#include
#include
#include
using namespace std;
class Token {
private:
std::string type;
std::string value;
public:
Token() { }
Token(std::string _type, std::string _value) {
type = _type;
value = _value;
}
~Token() { }
std::string _value() {
return value;
}
std::string _type() {
return type;
}
std::string str() {
if(type == "STRING") return ("Token(" + type + ", \"" + value + "\")");
else return ("Token(" + type + ", '" + value + "')");
}
};
class ASTNode {
public:
std::vector child;
Token token;
ASTNode() { }
ASTNode(Token _token) {
token = _token;
}
~ASTNode() { }
void make_child(ASTNode _node) {
ASTNode *temp = new ASTNode(_node._token());
temp->child = _node.child;
child.push_back(temp);
}
Token _token() {
return token;
}
void show(int level) {
std::cout << std::string(level * 2, ' ') << token.str() << "\n";
for(auto it = child.begin(); it != child.end(); it++) (*it)->show(level + 1);
}
};
int main () {
ASTNode ast = ASTNode(Token("STMT_LIST", "STMT_LIST"));
ASTNode ass = ASTNode(Token("ASSIGN", "="));
ass.make_child(Token("VARIABLE", "f"));
ass.make_child(Token("FLOAT", "3.14159"));
ast.make_child(ass);
ass = ASTNode(Token("ASSIGN", "="));
ass.make_child(Token("VARIABLE", "g"));
ass.make_child(Token("FLOAT", "1.05"));
ast.make_child(ass);
ASTNode reass = ASTNode(Token("ASSIGN", "="));
reass.make_child(Token("VARIABLE", "fg"));
ASTNode readd = ASTNode(Token("ADD", "+"));
readd.make_child(Token("VARIABLE", "f"));
readd.make_child(Token("VARIABLE", "g"));
reass.make_child(readd);
ast.make_child(reass);
ast.show(0);
return 0;
}
See also [[coding:c#classes|classes in c]]
=====Local Classes=====
void bar()
{
struct LocalClass
{
int operator()(int a, int b) const { return a + b; }
} f;
int n = f(1, 2);
}
=====Local Structs=====
Pre C++11, ''localize'' a function to a function
int foo () {
struct Local {
static int bar () {
return 1;
}
};
return Local::bar();
}
int foo (int x) {
struct Local {
int & x;
Local (int & x) : x(x) {}
int bar (int y) {
return x * x + y;
}
};
return Local(x).bar(44);
}
=====Functor=====
A functor is pretty much just a class which defines the operator(). That lets you create objects which "look like" a function:
#include
struct add_x {
add_x(int val) : x(val) {} // Constructor
int operator()(int y) const { return x + y; }
private:
int x;
};
int main() {
add_x add42(42);
int i = add42(8);
printf("%d", i);
return 0;
}
=====Templates=====
Templates werden mit dem Schlüsselwort "template" eingeleitet, gefolgt von der Template-Deklaration in spitzen Klammern ("<" und ">"). In der Template-Deklaration werden die Template-Parameter definiert, die den generischen Datentyp repräsentieren.
#include
template
void swap(T& a, T& b) {
T temp = a;
a = b;
b = temp;
}
template
class Stack {
private:
T* data;
int size;
int capacity;
public:
Stack(int capacity) {
this->capacity = capacity;
this->size = 0;
this->data = new T[capacity];
}
void push(const T& element) {
if (size < capacity) {
data[size] = element;
size++;
} else {
std::cout << "Stack is full. Cannot push element." << std::endl;
}
}
T pop() {
if (size > 0) {
size--;
return data[size];
} else {
std::cout << "Stack is empty. Cannot pop element." << std::endl;
return T(); // Return a default value for type T
}
}
};
int main() {
int a = 5, b = 10;
swap(a, b); // Der Compiler generiert swap(a, b)
double x = 2.5, y = 7.8;
swap(x, y); // Der Compiler generiert swap(x, y)
Stack intStack(10);
intStack.push(1);
intStack.push(2);
intStack.push(3);
int poppedIntElement = intStack.pop();
std::cout << "Popped element: " << poppedIntElement << std::endl;
Stack doubleStack(10);
doubleStack.push(1.2);
doubleStack.push(2.4);
doubleStack.push(3.14159);
double poppedDoubleElement = doubleStack.pop();
std::cout << "Popped element: " << poppedDoubleElement << std::endl;
return 0;
}
* [[http://www.cplusplus.com/doc/oldtutorial/templates/]]
* [[https://www.codeproject.com/Articles/48575/How-to-define-a-template-class-in-a-h-file-and-imp|Codeproject article]]
* http://www.willemer.de/informatik/cpp/cpptempl.htm
* http://www.angelikalanger.com/Articles/Cuj/ExpressionTemplates/ExpressionTemplates.htm
#include
using namespace std;
template void display(T1 x, T2 y);
int main(){
display(1,2);
display("Hello",3.14159);
return 0;
}
template void display(T1 x, T2 y) {
std::cout << x << " and " << y << "\n";
}
#include
using namespace std;
template
class Calculator{
public:
Calculator();
TYPE Add(TYPE param1, TYPE param2);
};
template
Calculator::Calculator() {}
template
TYPE Calculator::Add(TYPE param1, TYPE param2) {
cout << "Calculator::sum " << param1 << " " << param2 << endl;
TYPE result = param1 + param2 ;
return result;
}
int main(int argc, const char * argv[]) {
Calculator calcI;
cout << "outI : " << calcI.Add(65, 66) << "\n";
Calculator calcF;
cout << "outF : " << calcF.Add(6.5, 6.6) << "\n";
Calculator calcS;
cout << "outS : " << calcS.Add("A", "B") << "\n";
return 0;
}
You can fake templates in c using [[coding:c#preprocessing|preprocessing]]
=====Closures=====
void foo()
{
auto f = [](int a, int b) -> int { return a + b; };
auto n = f(1, 2);
}
=====Polymorphism=====
Use keyword virtual to override class methods. [[https://www.youtube.com/watch?v=kxKKHKSMGIg|Youtube - c++ Polimorphism]]
#include
using namespace std;
class Shape {
protected:
int width, height;
public:
Shape( int a = 0, int b = 0){
width = a;
height = b;
}
virtual int area() {
cout << "Shape area: ";
return 0;
}
};
class Rectangle: public Shape {
public:
Rectangle( int a = 0, int b = 0):Shape(a, b) { }
int area () {
cout << "Rectangle area: ";
return (width * height);
}
};
class Triangle: public Shape {
public:
Triangle( int a = 0, int b = 0):Shape(a, b) { }
int area () {
cout << "Triangle area: ";
return (width * height / 2);
}
};
int main() {
Shape *shape;
Rectangle rec(13,5);
Triangle tri(5,13);
shape = &rec;
std::cout << shape->area() << endl;
shape = &tri;
std::cout << shape->area() << endl;
return 0;
}
=====Singletons=====
#include
using namespace std;
class Singleton {
public:
static Singleton* getInstance() {
if (m_instance == NULL)
m_instance = new Singleton;
return m_instance;
}
private:
// private constructor and destructor
Singleton() { cout << "Instance created!\n"; }
~Singleton() {}
// private copy constructor and assignment operator
Singleton(const Singleton&);
Singleton& operator=(const Singleton&);
static Singleton *m_instance;
};
Singleton* Singleton::m_instance = nullptr;
int main(int argc, const char * argv[]) {
Singleton *singleton;
singleton = singleton->getInstance();
cout << singleton << "\n";
Singleton *anotherSingleton;
anotherSingleton = anotherSingleton->getInstance();
cout << anotherSingleton << "\n";
return 0;
}
=====Constants=====
Das Schlüsselwort "const" (konstant) wird verwendet um zu definieren dass eine Variable oder ein Objekt nicht verändert werden kann. Ein Versuch den Wert zu ändern, führt zu einem Kompilierungsfehler.
const int x = 5;
x = 10; // Kompilierungsfehler: Assignment an eine konstante Variable nicht erlaubt
Mit einer Konstanten kann man z.B auch die Länge eines Array zur Laufzeit definieren.
const int arraySize = 10;
int myArray[arraySize]; // Verwendung eines konstanten Ausdrucks für die Arraygröße
See also [[coding:c#constants|constants in C]]
=====Punning=====
"Type punning" bezieht sich auf die Praxis, Speicherbereiche mit einer bestimmten Datentyp-Interpretation zu verwenden, die nicht dem ursprünglichen Typ entsprechen, um auf die darin enthaltenen Daten zuzugreifen. Ein klassisches Beispiel ist die Manipulation von Bits innerhalb eines Integers, um spezielle Flags oder Optionen zu setzen oder zu überprüfen.
unsigned int options = 0;
options |= (1 << 2); // Set the third bit to 1
options &= ~(1 << 0); // Clear the first bit
* Pointer conversion
* union
* reinterpret_cast
Type punning wird nicht als "good practice" angesehen weil Datentypen auf verschiedene Weisen von Systemen interpretiert werden können..
=====Casting=====
=====Links=====
[[https://www.heise.de/developer/artikel/C-20-Die-vier-grossen-Neuerungen-4568956.html|C++ 20 Neuerungen]]