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. Sie haben bereits gesehen, wie Lambdas mit std::transform verwendet werden. Lassen Sie uns sowohl Funktoren als auch Lambda-Ausdrücke untersuchen – zwei Möglichkeiten, aufrufbare Objekte in C++ zu erstellen.

Ein Funktor (Funktionsobjekt) ist eine Klasse, die den operator() überlädt, wodurch Instanzen wie Funktionen aufgerufen werden können:

#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}
}

Jede Funktor-Instanz kann ihren eigenen unabhängigen Zustand durch Elementvariablen tragen, die bei der Konstruktion gesetzt werden – etwas, das ein gewöhnlicher Funktionsaufruf nicht leisten kann. Die Definition einer Klasse für einfache Operationen ist jedoch wortreich. Lambda-Ausdrücke bieten eine prägnante 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 gibt an, auf welche externen Variablen das Lambda zugreifen kann. Verwenden Sie [=], um alle per Wert zu erfassen, [&], um alle per Referenz zu erfassen, oder listen Sie spezifische Variablen auf, wie [factor] oder [&factor].

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

Lassen Sie uns einen Preisrechner erstellen, der sowohl Funktoren als auch Lambda-Ausdrücke demonstriert, um verschiedene Rabattstrategien auf Produktpreise anzuwenden.

Sie werden Ihren Code in zwei Dateien organisieren:

  • Discounts.h: Definieren Sie hier Ihre Rabatt-Funktoren und Hilfsfunktionen.

    Erstellen Sie einen Funktor namens PercentageDiscount, der einen Rabattprozentsatz (als Ganzzahl) speichert. Sein operator() sollte einen double Preis entgegennehmen und den rabattierten Preis zurückgeben. Zum Beispiel sollte ein Rabatt von 20% auf $100 den Wert $80 zurückgeben.

    Erstellen Sie einen weiteren Funktor namens FixedDiscount, der einen festen Abzugsbetrag (als double) speichert. Sein operator() sollte einen Preis entgegennehmen und den Preis abzüglich des festen Betrags zurückgeben (jedoch nie weniger als 0).

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

  • main.cpp: Lesen Sie fünf Eingaben ein (jede in einer separaten Zeile):
    1. Erster Produktpreis (double)
    2. Zweiter Produktpreis (double)
    3. Dritter Produktpreis (double)
    4. Anzuwendender prozentualer Rabatt (Ganzzahl, z. B. 20 für 20%)
    5. Fester Rabattbetrag (double)

    Erstellen Sie einen Vektor mit den drei Preisen und demonstrieren Sie beide Ansätze:

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

Zum Beispiel bei den Eingaben 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 es Ihnen, Funktoren (die einen Zustand wie den Rabattbetrag beibehalten) mit Lambdas (die Variablen für schnelle Inline-Operationen erfassen) zu vergleichen. Beide Ansätze arbeiten nahtlos mit STL-Algorithmen wie std::transform und std::sort zusammen.

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: "Original prices:" gefolgt von den Preisen mit printPrices ausgeben
    
    // TODO: std::transform mit dem Funktor PercentageDiscount verwenden
    // Erstelle einen neuen Vektor für die Ergebnisse
    // "After percentage discount:" gefolgt von den Ergebnissen ausgeben
    
    // TODO: std::transform mit dem Funktor FixedDiscount auf die ursprünglichen Preise anwenden
    // Erstelle einen neuen Vektor für die Ergebnisse
    // "After fixed discount:" gefolgt von den Ergebnissen ausgeben
    
    // TODO: std::transform mit einem Lambda verwenden, das jeden ursprünglichen Preis verdoppelt
    // Erstelle einen neuen Vektor für die Ergebnisse
    // "Premium prices (doubled):" gefolgt von den Ergebnissen ausgeben
    
    // TODO: std::sort mit einem Lambda verwenden, um die ursprünglichen Preise in absteigender Reihenfolge zu sortieren
    // "Sorted (high to low):" gefolgt von den sortierten Preisen ausgeben
    
    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