EMZETT.
Login

Kurz: set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON)

Teil des Kurses C++

Kapitel 14 von 15 im Kurs C++ (Abschnitt „Praxis“). Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

Projektstruktur

mein-projekt/
├─ CMakeLists.txt
├─ src/
│  ├─ main.cpp
│  ├─ rechner.cpp
│  └─ rechner.hpp
├─ tests/
│  └─ test_rechner.cpp
└─ build/              (erzeugt, nicht ins Repository)

CMake: das Standard-Buildsystem

cmake_minimum_required(VERSION 3.20)
project(MeinProjekt LANGUAGES CXX)
 
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
 
add_library(rechner src/rechner.cpp)
target_include_directories(rechner PUBLIC src)
 
add_executable(programm src/main.cpp)
target_link_libraries(programm PRIVATE rechner)
target_compile_options(programm PRIVATE -Wall -Wextra -Wpedantic)
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
./build/programm
ctest --test-dir build          # Tests ausführen

Abhängigkeiten holst du mit vcpkg, Conan oder CMakes FetchContent.

Header und Quelle

// rechner.hpp
#pragma once
 
int addiere(int a, int b);
 
// rechner.cpp
#include "rechner.hpp"
int addiere(int a, int b) { return a + b; }

#pragma once (oder Include-Guards) verhindert doppeltes Einbinden. Templates und inline-Funktionen stehen komplett im Header.

Tests

Das Mini-Prinzip ohne Bibliothek:

#include <iostream>
#include <string>
#include <cmath>
 
int fehler = 0;
#define PRUEFE(bedingung) do { \
    if (!(bedingung)) { ++fehler; std::cout << "FEHLER Zeile " << __LINE__ << ": " #bedingung "\n"; } \
    else std::cout << "ok: " #bedingung "\n"; } while (0)
 
bool istPalindrom(const std::string& s) {
    std::string t;
    for (unsigned char c : s) if (std::isalnum(c)) t += static_cast<char>(std::tolower(c));
    return std::equal(t.begin(), t.begin() + t.size() / 2, t.rbegin());
}
 
int main() {
    PRUEFE(istPalindrom("Anna"));
    PRUEFE(istPalindrom("Ein Esel lese nie"));
    PRUEFE(!istPalindrom("Hallo"));
    PRUEFE(istPalindrom(""));
    PRUEFE(std::abs(0.1 + 0.2 - 0.3) < 1e-9);
    std::cout << fehler << " Fehler\n";
    return fehler;
}

Ausgabe:

ok: istPalindrom("Anna")
ok: istPalindrom("Ein Esel lese nie")
ok: !istPalindrom("Hallo")
ok: istPalindrom("")
ok: std::abs(0.1 + 0.2 - 0.3) < 1e-9
0 Fehler

Für echte Projekte nimm ein Framework: Catch2, GoogleTest oder doctest.

TEST_CASE("addiere") {
    REQUIRE(addiere(2, 3) == 5);
    REQUIRE(addiere(-1, 1) == 0);
}

Werkzeuge

WerkzeugZweck
-Wall -Wextra -Wpedantic -Wconversion -WshadowWarnungen
-fsanitize=address,undefined,threadLaufzeitprüfung
clang-tidystatische Analyse, Modernisierungsvorschläge
clang-formateinheitliche Formatierung
cppcheckweitere Analyse
Valgrind, gdb, lldbSpeicherfehler, Debugger
Compiler Explorer (godbolt.org)Assembler-Ausgabe ansehen
Profiler (perf, gprof)Leistung messen

Die C++ Core Guidelines (Auswahl)

  1. Ressourcen besitzt ein Objekt (RAII). Kein rohes new/delete.
  2. Bevorzuge Werte und Standardcontainer (vector, string) vor Zeigern.
  3. Rule of Zero: Keine selbst geschriebenen Spezialfunktionen, wenn nicht nötig.
  4. const überall, wo möglich; Parameter als const& oder Wert.
  5. override, [[nodiscard]], explicit für Konstruktoren mit einem Parameter.
  6. Algorithmen und Ranges statt handgeschriebener Schleifen.
  7. Keine Makros für Konstanten und Funktionen; constexpr, inline, Templates.
  8. Typsichere Auswahl: enum class, std::variant, std::optional.
  9. Aussagekräftige Namen, kleine Funktionen, klare Zuständigkeiten.
  10. Fehler früh und laut: assert, Ausnahmen, static_assert.

Typische Anfängerfallen

FalleLösung
using namespace std; im Headervermeiden, std:: schreiben
Referenz/Zeiger auf lokale Variable zurückgebenWert zurückgeben
Vergleich von vorzeichenbehafteten mit size_tstd::ssize oder passende Typen
Iteratoren nach push_back weiterbenutzenneu holen
Basisklasse ohne virtuellen Destruktorvirtual ~Basis() = default;
Integer-Division: 1 / 2 ist 01.0 / 2
std::map::operator[] legt Einträge anfind/contains
Uninitialisierte lokale Variablenimmer mit {} initialisieren
Daten werden im Header definiert (mehrfach)inline/constexpr oder .cpp

Wie geht es weiter?

  • Bücher: “A Tour of C++” (Stroustrup, kompakt), “Effective Modern C++” (Meyers), “C++ Core Guidelines” (frei online)
  • Referenz: cppreference.com
  • Üben: Exercism, Advent of Code, eigene Spiele mit SDL oder SFML, Qt für Oberflächen
  • Spezialgebiete: Spiele (Unreal Engine), Eingebettetes (Arduino, ESP32), Systeme, Hochleistungsrechnen

Merke

  • CMake baut Projekte; Header (.hpp) deklarieren, .cpp setzen um
  • Tests mit Catch2 oder GoogleTest, Warnungen und Sanitizer immer an
  • Core Guidelines: RAII, Rule of Zero, const, Standardcontainer, keine Makros
  • clang-tidy und clang-format sichern Qualität
  • Moderne Sprachmittel (enum class, Smart Pointer, Ranges) machen C++ sicher und lesbar

Übungsaufgabe

Lege ein CMake-Projekt mit einer Bibliothek (rechner) und einem Test an, schalte Warnungen und den AddressSanitizer an.

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: Ranges, Module und weitere moderne Features

Weiter: Nachschlagen: Spickzettel

Alle Kapitel: C++ im Überblick