Menu
Coddy logo textTech

Funktoren & Lambda-Ausdrücke

Teil des Abschnitts Objektorientierte Programmierung der C++-Journey von Coddy. Lektion 74 von 104.

Viele STL-Algorithmen akzeptieren ein aufrufbares Objekt, das ihr Verhalten anpasst. Du hast bereits gesehen, wie lambdas mit std::transform verwendet werden. Sehen wir uns sowohl functor als auch lambda-Ausdrücke an – zwei Möglichkeiten, aufrufbare Objekte in C++ zu erstellen.

Ein functor (Funktionsobjekt) ist ein class, die den operator() überlädt und dadurch ermöglicht, Instanzen wie Funktionen aufzurufen:

#include <algorithm>
#include <vector>
#include <iostream>

struct MultiplyBy {
    int factor;
    MultiplyBy(int f) : factor(f) {}
    
    int operator()(int x) const {
        return x * factor;
    }
};

int main() {
    std::vector<int> nums = {1, 2, 3, 4};
    std::vector<int> result(nums.size());
    
    std::transform(nums.begin(), nums.end(), result.begin(), MultiplyBy(3));
    // result: {3, 6, 9, 12}
}

Each Funktorinstanz kann ihren eigenen unabhängigen Zustand über bei der Erstellung gesetzte Membervariablen führen – etwas, das ein gewöhnlicher function-Aufruf nicht kann. Die Definition einer class für einfache Operationen ist jedoch ausführlich. Lambda-Ausdrücke bieten eine kompakte Alternative:

int factor = 3;
std::transform(nums.begin(), nums.end(), result.begin(),
               [factor](int x) { return x * factor; });

Die Lambda-Syntax lautet [capture](parameters) { body }. Die Capture-Klausel legt fest, auf welche Variablen außerhalb die Lambda zugreifen kann. Verwende [=], um alle per Wert zu erfassen, [&], um alle per Referenz zu erfassen, oder liste bestimmte Variablen wie [factor] oder [&factor] auf.

Lambdas sind besonders nützlich für einmalige Operationen mit Algorithmen wie dem Sortieren nach benutzerdefinierten Kriterien:

std::vector<int> nums = {5, -2, 8, -1};
std::sort(nums.begin(), nums.end(), 
          [](int a, int b) { return std::abs(a) < std::abs(b); });
// Sortiert nach Absolutwert: {-1, -2, 5, 8}
challenge icon

Aufgabe

Einfach

Erstellen wir einen Preisrechner, der sowohl Funktoren als auch Lambda-Ausdrücke demonstriert, um verschiedene Rabattstrategien auf Produktpreise anzuwenden.

Du organisierst deinen Code auf zwei Dateien:

  • Discounts.h: Definiere hier deine Rabattfunktoren und Hilfsfunktionen.

    Erstelle einen Funktor namens PercentageDiscount, der einen Rabattprozentsatz (als integer) speichert. Sein operator() soll einen double-Preis entgegennehmen und den rabattierten Preis zurückgeben. Beispielsweise sollte ein Rabatt von 20 % auf $100 den Wert $80 zurückgeben.

    Erstelle einen weiteren Funktor namens FixedDiscount, der einen festen abzuziehenden Betrag (als double) speichert. Sein operator() soll einen Preis entgegennehmen und den Preis minus den festen Betrag zurückgeben (aber never unter 0).

    Erstelle eine Funktion namens printPrices, die ein const std::vector<double>& entgegennimmt und alle Preise durch Leerzeichen getrennt, gefolgt von einem Zeilenumbruch, ausgibt. Formatiere jeden Preis mit zwei Dezimalstellen.

  • main.cpp: Lies fünf inputs ein (jeweils in einer eigenen Zeile):
    1. Preis des ersten Produkts (double)
    2. Preis des zweiten Produkts (double)
    3. Preis des dritten Produkts (double)
    4. Anzuwendender prozentualer Rabatt (integer, z. B. 20 für 20 %)
    5. Fester Rabattbetrag (double)

    Erstelle einen Vektor mit den drei Preisen und demonstriere beide Ansätze:

    1. Gib Original prices: gefolgt von den Preisen aus
    2. Verwende std::transform mit deinem PercentageDiscount-Funktor, um einen neuen Vektor mit rabattierten Preisen zu erstellen. Gib After percentage discount: gefolgt von den Ergebnissen aus
    3. Verwende std::transform mit deinem FixedDiscount-Funktor auf den Originalpreisen, um einen weiteren Vektor zu erstellen. Gib After fixed discount: gefolgt von den Ergebnissen aus
    4. Verwende std::transform mit einem Lambda-Ausdruck, der jeden Originalpreis verdoppelt. Gib Premium prices (doubled): gefolgt von den Ergebnissen aus
    5. Verwende std::sort mit einem Lambda, um die Originalpreise in absteigender Reihenfolge zu sortieren. Gib Sorted (high to low): gefolgt von den sortierten Preisen aus

Beispielsweise mit den inputs 100.00, 50.00, 75.00, 20 und 15.00:

Original prices: 100.00 50.00 75.00 
After percentage discount: 80.00 40.00 60.00 
After fixed discount: 85.00 35.00 60.00 
Premium prices (doubled): 200.00 100.00 150.00 
Sorted (high to low): 100.00 75.00 50.00 

Diese Herausforderung ermöglicht dir, Funktoren (die state wie den Rabattbetrag beibehalten) mit Lambdas (die Variablen für schnelle Inline-Operationen erfassen) zu vergleichen. Beide Ansätze funktionieren nahtlos mit STL-Algorithmen wie std::transform und std::sort.

Probier es selbst

#include <iostream>
#include <vector>
#include <algorithm>
#include "Discounts.h"

int main() {
    // Eingaben lesen
    double price1, price2, price3;
    int percentageDiscount;
    double fixedDiscount;
    
    std::cin >> price1;
    std::cin >> price2;
    std::cin >> price3;
    std::cin >> percentageDiscount;
    std::cin >> fixedDiscount;
    
    // Erstelle einen Vektor mit den drei Preisen
    std::vector<double> prices = {price1, price2, price3};
    
    // TODO: Print "Original prices:" followed by the prices using printPrices
    
    // TODO: Use std::transform with PercentageDiscount functor
    // Erstelle einen neuen Vektor für die Ergebnisse
    // Print "After percentage discount:" followed by the results
    
    // TODO: Use std::transform with FixedDiscount functor on original prices
    // Erstelle einen neuen Vektor für die Ergebnisse
    // Print "After fixed discount:" followed by the results
    
    // TODO: Use std::transform with a lambda that doubles each original price
    // Erstelle einen neuen Vektor für die Ergebnisse
    // Print "Premium prices (doubled):" followed by the results
    
    // TODO: Use std::sort with a lambda to sort original prices in descending order
    // Print "Sorted (high to low):" followed by the sorted prices
    
    return 0;
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-C++-Compiler