Menu
Coddy logo textTech

Functor'lar ve Lambda İfadeleri

Coddy'nin C++ Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 74 / 104.

Birçok STL algoritması, davranışlarını özelleştiren çağrılabilir bir nesneyi kabul eder. std::transform ile lambda ifadelerinin kullanıldığını zaten gördün. Hem functor’ları hem de lambda ifadelerini — C++’ta çağrılabilir nesneler oluşturmanın iki yolunu — inceleyelim.

Functor (fonksiyon nesnesi), operator() işlecini aşırı yükleyen ve örneklerinin fonksiyonlar gibi çağrılmasına olanak tanıyan bir sınıftır:

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

Her functor örneği, oluşturulurken ayarlanan üye değişkenler aracılığıyla kendi bağımsız durumunu taşıyabilir; sıradan bir işlev çağrısı bunu yapamaz. Ancak basit işlemler için bir sınıf tanımlamak ayrıntı gerektirir. Lambda ifadeleri kısa ve öz bir alternatif sunar:

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

Lambda sözdizimi [capture](parameters) { body } şeklindedir. Yakalama yan tümcesi, lambda'nın hangi dış değişkenlere erişebileceğini belirtir. Tüm değişkenleri değer yoluyla yakalamak için [=], tüm değişkenleri referans yoluyla yakalamak için [&] kullanın veya [factor] ya da [&factor] gibi belirli değişkenleri listeleyin.

Lambdalar, özel ölçütlerle sıralama gibi algoritmalarla tek seferlik işlemler için özellikle kullanışlıdır:

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); });
// Mutlak değere göre sıralandı: {-1, -2, 5, 8}
challenge icon

Görev

Kolay

Ürün fiyatlarına farklı indirim stratejileri uygulamak için hem functor'ları hem de lambda ifadelerini gösteren bir fiyat hesaplayıcı oluşturalım.

Kodunuzu iki dosyaya ayıracaksınız:

  • Discounts.h: İndirim functor'larınızı ve yardımcı işlevlerinizi burada tanımlayın.

    Bir indirim yüzdesini (tam sayı olarak) saklayan PercentageDiscount adlı bir functor oluşturun. operator() işlevi bir double fiyat almalı ve indirimli fiyatı döndürmelidir. Örneğin, $100 için %20 indirim $80 döndürmelidir.

    Çıkarılacak sabit bir miktarı (bir FixedDiscount olarak) saklayan double adlı başka bir functor oluşturun. operator() işlevi bir fiyat almalı ve sabit miktarın çıkarıldığı fiyatı döndürmelidir (ancak sonuç hiçbir zaman 0'ın altında olmamalıdır).

    Bir printPrices alan ve tüm fiyatları boşluklarla ayırarak, ardından bir satır sonu ekleyerek yazdıran const std::vector<double>& adlı bir işlev oluşturun. Her fiyatı iki ondalık basamakla biçimlendirin.

  • main.cpp: Beş girdi okuyun (her biri ayrı bir satırda):
    1. Birinci ürün fiyatı (double)
    2. İkinci ürün fiyatı (double)
    3. Üçüncü ürün fiyatı (double)
    4. Uygulanacak yüzde indirimi (tam sayı; örneğin, %20 için 20)
    5. Sabit indirim miktarı (double)

    Üç fiyatı içeren bir vektör oluşturun ve her iki yaklaşımı gösterin:

    1. Fiyatların önünde Original prices: yazdırın
    2. İndirimli fiyatlardan oluşan yeni bir vektör oluşturmak için std::transform functor'ınızla PercentageDiscount kullanın. Sonuçların önünde After percentage discount: yazdırın
    3. Başka bir vektör oluşturmak için özgün fiyatlar üzerinde std::transform functor'ınızla FixedDiscount kullanın. Sonuçların önünde After fixed discount: yazdırın
    4. Her özgün fiyatı iki katına çıkaran bir lambda ifadesiyle std::transform kullanın. Sonuçların önünde Premium prices (doubled): yazdırın
    5. Özgün fiyatları azalan düzende sıralamak için bir lambda ile std::sort kullanın. Sıralanmış fiyatların önünde Sorted (high to low): yazdırın

Örneğin, girdiler 100.00, 50.00, 75.00, 20 ve 15.00 olduğunda:

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 

Bu alıştırma, functor'ları (indirim miktarı gibi durumu koruyan) lambda'larla (hızlı, satır içi işlemler için değişkenleri yakalayan) karşılaştırmanızı sağlar. Her iki yaklaşım da std::transform ve std::sort gibi STL algoritmalarıyla sorunsuz bir şekilde çalışır.

Kendin dene

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

int main() {
    // Girdileri oku
    double price1, price2, price3;
    int percentageDiscount;
    double fixedDiscount;
    
    std::cin >> price1;
    std::cin >> price2;
    std::cin >> price3;
    std::cin >> percentageDiscount;
    std::cin >> fixedDiscount;
    
    // Üç fiyatla bir vektör oluştur
    std::vector<double> prices = {price1, price2, price3};
    
    // TODO: Print "Original prices:" followed by the prices using printPrices
    
    // TODO: Use std::transform with PercentageDiscount functor
    // Sonuçlar için yeni bir vektör oluştur
    // Print "After percentage discount:" followed by the results
    
    // TODO: Use std::transform with FixedDiscount functor on original prices
    // Sonuçlar için yeni bir vektör oluştur
    // Print "After fixed discount:" followed by the results
    
    // TODO: Use std::transform with a lambda that doubles each original price
    // Sonuçlar için yeni bir vektör oluştur
    // 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 iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Online C++ derleyicisi