Skip to content

01 Cpp Grundlagen

gideon edited this page Oct 24, 2024 · 2 revisions

Zusammenfassung der Slides "C++ Grundlagen" mit passenden Codebeispielen

1. C++: Die Anfänge und die Entwicklung bis zum ISO/IEC-Standard

C++ wurde 1979 von Bjarne Stroustrup als "C with Classes" entwickelt, um objektorientierte Konzepte in C zu integrieren. 1983 wurde der Name in C++ geändert, und viele neue Funktionen wurden hinzugefügt. Zwischen 1990 und 1998 kamen Templates, Ausnahmen, Namensräume und die Standard Template Library (STL) hinzu. Die Normierung erfolgte 1998 (ISO/IEC 14882:1998).

2. Modernes C++

  • C++11 führte viele neue Funktionen ein, darunter Move-Semantik, Smart Pointer, Lambdas und Typinferenz.
    Beispiel für eine Lambda-Funktion:

    auto add = [](int a, int b) { return a + b; };
    std::cout << add(3, 4) << std::endl;  // Ausgabe: 7

    Beispiel für Smart Pointer:

    #include <memory>
    
    std::unique_ptr<int> p = std::make_unique<int>(10);
    std::cout << *p << std::endl;  // Ausgabe: 10
  • C++14 brachte Verbesserungen wie generische Lambda-Ausdrücke und benutzerdefinierte Literale.
    Beispiel für generische Lambda:

    auto multiply = [](auto a, auto b) { return a * b; };
    std::cout << multiply(3, 4.5) << std::endl;  // Ausgabe: 13.5
  • C++17 führte u. a. parallele Algorithmen, std::variant und std::optional ein.
    Beispiel für std::optional:

    #include <optional>
    
    std::optional<int> getValue(bool flag) {
        if (flag) {
            return 42;
        }
        return std::nullopt;
    }
    
    auto value = getValue(true);
    if (value) {
        std::cout << "Wert: " << *value << std::endl;  // Ausgabe: Wert: 42
    }
  • C++20 fügte Konzepte, Module, Coroutinen und eine Ranges-Bibliothek hinzu.
    Beispiel für Coroutinen:

    #include <coroutine>
    #include <iostream>
    
    struct Generator {
        struct promise_type {
            int current_value;
            std::suspend_always yield_value(int value) {
                current_value = value;
                return {};
            }
            Generator get_return_object() { return Generator{this}; }
            std::suspend_always initial_suspend() { return {}; }
            std::suspend_never final_suspend() noexcept { return {}; }
            void return_void() {}
            void unhandled_exception() { std::terminate(); }
        };
        promise_type* promise;
        Generator(promise_type* p) : promise(p) {}
        struct iterator {
            promise_type* promise;
            bool operator!=(std::default_sentinel_t) const { return true; }
            void operator++() { promise->current_value++; }
            int operator*() const { return promise->current_value; }
        };
        iterator begin() { return iterator{promise}; }
        std::default_sentinel_t end() { return {}; }
    };
    
    Generator counter() {
        for (int i = 0; i < 5; ++i) {
            co_yield i;
        }
    }
    
    int main() {
        for (auto value : counter()) {
            std::cout << value << " ";  // Ausgabe: 0 1 2 3 4
        }
    }

3. C++23 Ausblick

Neue Funktionen umfassen Erweiterungen der Ranges-Bibliothek (views::chunk, views::zip), std::expected, Monadic Interfaces und Attribute für Lambdas.

4. Entwicklung von Klassen in C++

Klassen bestehen typischerweise aus einer Schnittstellendatei (Header) und einer Implementierungsdatei. Header-only-Bibliotheken enthalten den gesamten Code in Header-Dateien.
Beispiel für eine einfache Klassendeklaration und Implementierung:

// Header-Datei (Person.h)
#ifndef PERSON_H
#define PERSON_H
#include <string>

class Person {
private:
    std::string name;
    int age;

public:
    Person(const std::string& name, int age);
    void print() const;
};

#endif

// Implementierungsdatei (Person.cpp)
#include "Person.h"
#include <iostream>

Person::Person(const std::string& name, int age) : name(name), age(age) {}

void Person::print() const {
    std::cout << "Name: " << name << ", Age: " << age << std::endl;
}

// Nutzung der Klasse
#include "Person.h"

int main() {
    Person p("Alice", 30);
    p.print();  // Ausgabe: Name: Alice, Age: 30
    return 0;
}

5. Klassendeklarationen und Implementierung

Es gibt zwei Arten von Klassen: struct für öffentliche Mitglieder und class für private Mitglieder. Methoden werden in den Implementierungsdateien definiert.

6. Automatische Typinferenz

Das Schlüsselwort auto ermöglicht es, den Datentyp einer Variablen automatisch vom Initialisierungswert abzuleiten. decltype gibt den Deklarationstyp eines Ausdrucks zurück.
Beispiel:

auto x = 7;
double f();
auto g = f();
decltype(g) h = 5.5;

7. constexpr

Das Schlüsselwort constexpr ermöglicht es, konstante Ausdrücke und Funktionen zur Kompilationszeit zu berechnen. Es wird verwendet, um konstante Werte effizienter zu definieren.
Beispiel:

constexpr int square(int x) {
    return x * x;
}
constexpr int value = square(5);  // Wert wird zur Kompilationszeit berechnet

8. Initialisierungslisten und vereinheitlichte Initialisierung

Mit Initialisierungslisten können mehrere Werte einfach an Konstruktoren übergeben werden. Die vereinheitlichte Initialisierung ({}) bietet eine einheitliche Syntax zur Initialisierung von Objekten.
Beispiel:

struct Point {
    int x, y;
};
Point p1{1, 2};  // vereinheitlichte Initialisierung
std::vector<int> vec = {1, 2, 3, 4};

9. Referenzen und Parameterübergabe

Referenzen (&) sind Aliasse für Variablen und ermöglichen eine effiziente Parameterübergabe ohne Datenkopie. Objekte können by Value, by Reference oder by Pointer an Funktionen übergeben werden.
Beispiel:

void increment(int& n) {
    ++n;
}

int main() {
    int value = 5;
    increment(value);
    std::cout << value << std::endl;  // Ausgabe: 6
}

10. Typkonvertierung

C++ bietet verschiedene Methoden zur Typkonvertierung:

  • static_cast: Normale Typkonvertierung

    double d = 3.14;
    int i = static_cast<int>(d);  // Konvertiert d zu einem int
  • dynamic_cast: Down-Casting in Klassenhierarchien

    class Base {
      virtual void foo() {}
    };
    class Derived : public Base {};
    
    Base* b = new Derived;
    Derived* d = dynamic_cast<Derived*>(b);
  • const_cast: Entfernt oder fügt const hinzu

    const int a = 10;
    int& b = const_cast<int&>(a);
    b = 20;
  • reinterpret_cast: Konvertierung ohne Compiler-Überprüfung

    int a = 65;
    char c = reinterpret_cast<char&>(a);  // Konvertiert int zu char

Diese Zusammenfassung bietet eine grundlegende Einführung in C++, beginnend bei der Geschichte der Sprache bis hin zu den neuesten Entwicklungen im modernen C++. Sie beleuchtet die wichtigsten Sprachfunktionen und deren Verwendung zur Entwicklung von Klassen und effizienten Programmen.