Inhaltsverzeichnis

improve

CPlusPlus oder auch (C++) ist eine objektorientierte Programmiersprache. Siehe auch C/C#.

Cpp reference

Classes

Klassen mit mindestens einer „virtual“ Funktion nennt man Polymorphe Klassen.

#include <iostream>
#include <string>
#include <vector>
 
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<ASTNode*> 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 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 <iostream>
 
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 <iostream>
 
template <typename T>
void swap(T& a, T& b) {
    T temp = a;
    a = b;
    b = temp;
}
 
template <typename T>
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<int>(a, b)
 
    double x = 2.5, y = 7.8;
    swap(x, y);  // Der Compiler generiert swap<double>(x, y)
 
    Stack<int> intStack(10);
    intStack.push(1);
    intStack.push(2);
    intStack.push(3);
    int poppedIntElement = intStack.pop();
    std::cout << "Popped element: " << poppedIntElement << std::endl;
 
    Stack<double> 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;
}
#include <iostream>
 
using namespace std;
template <typename T1, typename T2> void display(T1 x, T2 y);
 
int main(){
	display(1,2);
	display("Hello",3.14159);
	return 0;
}
 
template <typename T1, typename T2> void display(T1 x, T2 y) {
	std::cout << x << " and "  << y << "\n";
}
#include <iostream>
 
using namespace std;
 
template <class TYPE>
class Calculator{
    public:
        Calculator();
        TYPE Add(TYPE param1, TYPE param2);
};
 
template <class TYPE>
Calculator<TYPE>::Calculator() {}
 
template <class TYPE>
TYPE Calculator<TYPE>::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<int> calcI;
    cout << "outI : " << calcI.Add(65, 66) << "\n";
 
    Calculator<float> calcF;
    cout << "outF : " << calcF.Add(6.5, 6.6) << "\n";
 
    Calculator<string> calcS;
    cout << "outS : " << calcS.Add("A", "B") << "\n";
 
    return 0;
 
}

You can fake templates in c using 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. Youtube - c++ Polimorphism

#include <iostream> 
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 <iostream>
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 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

Type punning wird nicht als „good practice“ angesehen weil Datentypen auf verschiedene Weisen von Systemen interpretiert werden können..

Casting

C++ 20 Neuerungen