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 kullanılan lambda ifadelerini daha önce gördün. Şimdi C++'ta çağrılabilir nesneler oluşturmanın iki yolu olan hem functor hem de lambda expressions kavramlarını inceleyelim.

Bir functor (işlev nesnesi), operator() aşırı yükleyen ve örneklerin işlevler gibi çağrılmasına olanak tanıyan bir class'tı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 funktör örneği, oluşturma sırasında 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ılıdır. 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ünü değerle yakalamak için [=], tümünü referansla 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 dosya arasında düzenleyeceksiniz:

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

    İndirim yüzdesini (integer olarak) depolayan PercentageDiscount adlı bir functor oluşturun. operator(), bir double fiyat almalı ve indirimli fiyatı döndürmelidir. Örneğin, $100 üzerinden %20 indirim $80 döndürmelidir.

    Çıkarılacak sabit miktarı (bir double olarak) depolayan FixedDiscount adlı başka bir functor oluşturun. operator(), bir fiyat almalı ve sabit miktar çıkarılmış fiyatı döndürmelidir (ancak sonuç never 0'ın altında olmamalıdır).

    Bir const std::vector<double>& alan ve tüm fiyatları aralarında boşluk olacak şekilde, ardından bir newline gelecek biçimde yazdıran printPrices adlı bir function oluşturun. Her fiyatı iki ondalık basamakla Format edin.

  • main.cpp: Beş input 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 indirim yüzdesi (integer; örneğin, %20 için 20)
    5. Sabit indirim miktarı (double)

    Üç fiyatla bir vector oluşturun ve her iki yaklaşımı da gösterin:

    1. Original prices: metnini ve ardından fiyatları yazdırın
    2. İndirimli fiyatlardan yeni bir vector oluşturmak için PercentageDiscount functor'ınızla std::transform kullanın. After percentage discount: metnini ve ardından sonuçları yazdırın
    3. Orijinal fiyatlar üzerinde başka bir vector oluşturmak için FixedDiscount functor'ınızla std::transform kullanın. After fixed discount: metnini ve ardından sonuçları yazdırın
    4. Her bir orijinal fiyatı doubled yapan bir lambda expression ile std::transform kullanın. Premium prices (doubled): metnini ve ardından sonuçları yazdırın
    5. Orijinal fiyatları descending order biçiminde sıralamak için bir lambda ile std::sort kullanın. Sorted (high to low): metnini ve ardından sıralanmış fiyatları yazdırın

Örneğin, input değerleri 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 challenge, indirim miktarı gibi state'i koruyan functor'ları, hızlı ve satır içi işlemler için değişkenleri yakalayan lambda'larla karşılaştırmanıza olanak tanır. Her iki yaklaşım da std::transform ve std::sort gibi STL algoritmalarıyla sorunsuz ş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