Menu
Coddy logo textTech

Functors e Expressões Lambda

Parte da seção Programação Orientada a Objetos do Journey de C++ da Coddy. Lição 74 de 104.

Muitos algoritmos da STL aceitam um objeto chamável que personaliza seu comportamento. Você já viu lambdas usadas com std::transform. Vamos explorar tanto functors quanto expressões lambda — duas maneiras de criar objetos chamáveis em C++.

Um functor (objeto de função) é uma class que sobrecarrega o operator(), permitindo que as instâncias sejam chamadas como funções:

#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 instância de functor pode manter seu próprio estado independente por meio de variáveis-membro definidas na construção — algo que uma chamada de function comum não pode fazer. No entanto, definir uma class para operações simples é prolixo. Expressões lambda oferecem uma alternativa concisa:

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

A sintaxe de lambda é [capture](parameters) { body }. A cláusula de captura especifica quais variáveis externas a lambda pode acessar. Use [=] para capturar todas por valor, [&] para capturar todas por referência ou liste variáveis específicas, como [factor] ou [&factor].

As lambdas são particularmente úteis para operações pontuais com algoritmos como ordenação com critérios personalizados:

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); });
// Ordenado por valor absoluto: {-1, -2, 5, 8}
challenge icon

Desafio

Fácil

Vamos criar uma calculadora de preços que demonstre tanto functors quanto expressões lambda para aplicar diferentes estratégias de discount aos preços dos produtos.

Você organizará seu código em dois arquivos:

  • Discounts.h: Defina seus functors de discount e as funções utilitárias aqui.

    Crie um functor chamado PercentageDiscount que armazene uma porcentagem de discount (como um integer). Seu operator() deve receber um preço double e retornar o preço com discount. Por exemplo, um discount de 20% em $100 deve retornar $80.

    Crie outro functor chamado FixedDiscount que armazene um amount fixed a ser subtraído (como um double). Seu operator() deve receber um preço e retornar o preço menos o amount fixed (mas never abaixo de 0).

    Crie uma function chamada printPrices que receba um const std::vector<double>& e imprima all os preços separados por espaços, seguidos por uma newline. Use o Format de cada preço com duas casas decimais.

  • main.cpp: Leia cinco inputs (cada um em uma linha separada):
    1. Preço do primeiro produto (double)
    2. Preço do segundo produto (double)
    3. Preço do terceiro produto (double)
    4. Percentage discount a aplicar (integer, por exemplo, 20 para 20%)
    5. Fixed discount amount (double)

    Crie um vector com os três preços e demonstre ambas as abordagens:

    1. Imprima Original prices: seguido pelos preços
    2. Use std::transform com seu functor PercentageDiscount para criar um novo vector de preços com discount. Imprima After percentage discount: seguido pelos resultados
    3. Use std::transform com seu functor FixedDiscount nos preços original para criar outro vector. Imprima After fixed discount: seguido pelos resultados
    4. Use std::transform com uma expressão lambda que faça o dobro de each preço original. Imprima Premium prices (doubled): seguido pelos resultados
    5. Use std::sort com uma lambda para ordenar os preços original em ordem descending. Imprima Sorted (high to low): seguido pelos preços ordenados

Por exemplo, com os inputs 100.00, 50.00, 75.00, 20 e 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 

Este desafio permite comparar functors (que mantêm estado, como o discount amount) com lambdas (que capturam variáveis para operações rápidas e inline). Ambas as abordagens funcionam perfeitamente com algoritmos da STL, como std::transform e std::sort.

Experimente você mesmo

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

int main() {
    // Ler as entradas
    double price1, price2, price3;
    int percentageDiscount;
    double fixedDiscount;
    
    std::cin >> price1;
    std::cin >> price2;
    std::cin >> price3;
    std::cin >> percentageDiscount;
    std::cin >> fixedDiscount;
    
    // Criar um vetor com os três preços
    std::vector<double> prices = {price1, price2, price3};
    
    // TODO: Print "Original prices:" followed by the prices using printPrices
    
    // TODO: Use std::transform with PercentageDiscount functor
    // Criar um novo vetor para os resultados
    // Print "After percentage discount:" followed by the results
    
    // TODO: Use std::transform with FixedDiscount functor on original prices
    // Criar um novo vetor para os resultados
    // Print "After fixed discount:" followed by the results
    
    // TODO: Use std::transform with a lambda that doubles each original price
    // Criar um novo vetor para os resultados
    // 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 seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos

Pratique por conta própria: Compilador de C++ online