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}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
PercentageDiscountadlı bir functor oluşturun.operator(), birdoublefiyat almalı ve indirimli fiyatı döndürmelidir. Örneğin, $100 üzerinden %20 indirim $80 döndürmelidir.Çıkarılacak sabit miktarı (bir
doubleolarak) depolayanFixedDiscountadlı 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ıranprintPricesadlı bir function oluşturun. Her fiyatı iki ondalık basamakla Format edin.main.cpp: Beş input okuyun (her biri ayrı bir satırda):- Birinci ürün fiyatı (double)
- İkinci ürün fiyatı (double)
- Üçüncü ürün fiyatı (double)
- Uygulanacak indirim yüzdesi (integer; örneğin, %20 için 20)
- Sabit indirim miktarı (double)
Üç fiyatla bir vector oluşturun ve her iki yaklaşımı da gösterin:
Original prices:metnini ve ardından fiyatları yazdırın- İndirimli fiyatlardan yeni bir vector oluşturmak için
PercentageDiscountfunctor'ınızlastd::transformkullanın.After percentage discount:metnini ve ardından sonuçları yazdırın - Orijinal fiyatlar üzerinde başka bir vector oluşturmak için
FixedDiscountfunctor'ınızlastd::transformkullanın.After fixed discount:metnini ve ardından sonuçları yazdırın - Her bir orijinal fiyatı doubled yapan bir lambda expression ile
std::transformkullanın.Premium prices (doubled):metnini ve ardından sonuçları yazdırın - Orijinal fiyatları descending order biçiminde sıralamak için bir lambda ile
std::sortkullanı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;
}
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
1OOP Temelleri
Harici DosyalarC++ Build ve DerlemeBaşlık Dosyaları ve Kaynak DosyalarıAd Alanları ve KapsamC++'ta OOP'ye GirişSınıflar ve Nesneler'this' İşaretçisiMetotlar (Üye Fonksiyonlar)Öznitelikler (Veri Üyeleri)Ctor ve Dtor TemelleriÖzet - Basit Hesap Makinesi4Sınıf Özellikleri
Örnek ve Statik ÜyelerGetter ve Setter MetotlarıConst Üye FonksiyonlarMutable Anahtar KelimesiStatik Metotlar ve DeğişkenlerFriend Fonksiyonlar ve SınıflarÖzet - Banka Hesabı Yöneticisi7Kalıtım
Temel KalıtımKalıtım Erişim SeviyeleriCtor ve Dtor Çağrılma SırasıMetot Geçersiz KılmaSanal Fonksiyonlar ve VTableÇoklu KalıtımSanal KalıtımÖzet - Çalışan Hiyerarşisi10STL Genel Bakış
STL Genel Bakış ve FelsefesiSTL KonteynerleriİteratörlerSTL AlgoritmalarıFunctor'lar ve Lambda İfadeleriÖzet - Kelime Frekansı13Tasarım Kalıpları 1. Bölüm
Tasarım Kalıplarına GirişSingleton KalıbıFactory ve Abstract FactoryBuilder KalıbıObserver KalıbıStrategy Kalıbı2Bellek Yönetimi
Stack ve Heap Bellekİşaretçiler ve ReferanslarDinamik Bellek (new/delete)C++'ta Akıllı İşaretçilerC++'ta RAIIÖzet - Dinamik Dizi Yöneticisi5Kapsülleme
C++'da Erişim BelirleyicilerDerinlemesine Erişim BelirleyicilerBilgi GizlemeStruct vs Classİç İçe ve Dahili SınıflarÖzet - Öğrenci Kayıt Sistemi8Çok Biçimlilik
Derleme ve Çalışma Zamanı Çok BiçimliliğiFonksiyon Aşırı YüklemeSanal Fonksiyonlara Yeniden BakışSaf Sanal FonksiyonlarSoyut SınıflarC++'ta Arayüz TasarımıDynamic Casting ve RTTIÖzet - Şekil Hesaplayıcı3Yapıcılar ve Yıkıcılar
Varsayılan YapıcıParametreli YapıcıKopya YapıcıTaşıma YapıcısıYapıcı İlklendirme ListeleriTemsilci YapıcılarYıkıcılara Derinlemesine BakışÜç / Beş / Sıfır KuralıÖzet - String Sınıfı6Operatör Aşırı Yükleme
Operatör Aşırı Yüklemeye GirişAritmetik Operatör Aşırı YüklemeKarşılaştırma Operatörü Aşırı YüklemeStream OperatörleriAtama Operatörü Aşırı Yükleme[] ve () Operatör Aşırı YüklemeTip Dönüşüm OperatörleriÖzet - Matris Sınıfı9Şablonlar
Fonksiyon ŞablonlarıSınıf ŞablonlarıŞablon ÖzelleştirmeVariadic ŞablonlarSFINAE ve Type Traits TemelleriÖzet - Generic KonteynerKendi başına pratik yap: Online C++ derleyicisi