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 nesne kabul eder. std::transform ile kullanılan lambdaları zaten gördünüz. C++'ta çağrılabilir nesneler oluşturmanın iki yolu olan hem functor'ları hem de lambda ifadelerini inceleyelim.

Bir functor (fonksiyon nesnesi), operator() operatörünü aşırı yükleyerek örneklerin 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));
    // sonuç: {3, 6, 9, 12}
}

Her bir funktor örneği, oluşturma sırasında atanan üye değişkenler aracılığıyla kendi bağımsız durumunu taşıyabilir; bu, sıradan bir fonksiyon çağrısının yapamayacağı bir şeydir. Ancak, basit işlemler için bir sınıf tanımlamak çok fazla kod 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öz dizimi [capture](parameters) { body } şeklindedir. Yakalama (capture) ifadesi, lambdanın hangi dış değişkenlere erişebileceğini belirtir. Hepsini değere göre yakalamak için [=], hepsini referansa göre yakalamak için [&] kullanın veya [factor] ya da [&factor] gibi belirli değişkenleri listeleyin.

Lambda'lar, özel kriterlere göre sıralama gibi algoritmalarla yapılan 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ıralanmış hali: {-1, -2, 5, 8}
challenge icon

Görev

Kolay

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

Kodunuzu iki dosya halinde düzenleyeceksiniz:

  • Discounts.h: İndirim funktorlarınızı ve yardımcı fonksiyonlarınızı burada tanımlayın.

    Bir indirim yüzdesini (tam sayı olarak) saklayan PercentageDiscount adında bir funktor oluşturun. Bu funktorun operator() fonksiyonu bir double fiyat almalı ve indirimli fiyatı döndürmelidir. Örneğin, 100$ üzerindeki %20'lik bir indirim 80$ döndürmelidir.

    Çıkarılacak sabit bir tutarı (bir double olarak) saklayan FixedDiscount adında başka bir funktor oluşturun. Bu funktorun operator() fonksiyonu bir fiyat almalı ve fiyattan sabit tutarı çıkararak sonucu döndürmelidir (ancak sonuç asla 0'ın altına düşmemelidir).

    Bir const std::vector<double>& alan ve tüm fiyatları aralarında boşluk bırakarak yazdıran, ardından bir alt satıra geçen printPrices adında bir fonksiyon oluşturun. Her fiyatı virgülden sonra iki basamak olacak şekilde formatlayın.

  • main.cpp: Beş girişi 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 tutarı (double)

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

    1. Original prices: yazdırın ve ardından fiyatları listeleyin
    2. Yeni bir indirimli fiyatlar vektörü oluşturmak için PercentageDiscount funktorunuzla birlikte std::transform kullanın. After percentage discount: yazdırın ve ardından sonuçları listeleyin
    3. Orijinal fiyatlar üzerinde başka bir vektör oluşturmak için FixedDiscount funktorunuzla birlikte std::transform kullanın. After fixed discount: yazdırın ve ardından sonuçları listeleyin
    4. Her bir orijinal fiyatı iki katına çıkaran bir lambda ifadesi ile std::transform kullanın. Premium prices (doubled): yazdırın ve ardından sonuçları listeleyin
    5. Orijinal fiyatları büyükten küçüğe sıralamak için bir lambda ile std::sort kullanın. Sorted (high to low): yazdırın ve ardından sıralanmış fiyatları listeleyin

Örneğin, 100.00, 50.00, 75.00, 20 ve 15.00 girişleri ile:

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 meydan okuma, funktorları (indirim tutarı gibi durumları koruyan) lambdalarla (hızlı, satır içi işlemler için değişkenleri yakalayan) karşılaştırmanıza olanak tanır. 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;
    
    // Üç fiyatı içeren bir vektör oluştur
    std::vector<double> prices = {price1, price2, price3};
    
    // TODO: "Original prices:" yazdır ve ardından printPrices kullanarak fiyatları listele
    
    // TODO: PercentageDiscount funktoru ile std::transform kullan
    // Sonuçlar için yeni bir vektör oluştur
    // "After percentage discount:" yazdır ve ardından sonuçları listele
    
    // TODO: Orijinal fiyatlar üzerinde FixedDiscount funktoru ile std::transform kullan
    // Sonuçlar için yeni bir vektör oluştur
    // "After fixed discount:" yazdır ve ardından sonuçları listele
    
    // TODO: Her bir orijinal fiyatı ikiye katlayan bir lambda ile std::transform kullan
    // Sonuçlar için yeni bir vektör oluştur
    // "Premium prices (doubled):" yazdır ve ardından sonuçları listele
    
    // TODO: Orijinal fiyatları azalan düzende sıralamak için bir lambda ile std::sort kullan
    // "Sorted (high to low):" yazdır ve ardından sıralanmış fiyatları listele
    
    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