Functor dan Ekspresi Lambda
Termasuk bagian Pemrograman Berorientasi Object dalam perjalanan C++ di Coddy. Pelajaran 74 dari 104.
Banyak algoritma STL menerima object yang dapat dipanggil untuk menyesuaikan perilakunya. Kamu sudah melihat lambda digunakan dengan std::transform. Mari kita pelajari functor dan ekspresi lambda, dua cara untuk membuat object yang dapat dipanggil di C++.
functor (object fungsi) adalah class yang melakukan overload pada operator(), sehingga instansnya dapat dipanggil seperti fungsi:
#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}
}Setiap instance functor dapat membawa state independennya sendiri melalui variabel anggota yang ditetapkan saat konstruksi, sesuatu yang tidak dapat dilakukan oleh pemanggilan fungsi biasa. Namun, mendefinisikan class untuk operasi sederhana terasa bertele-tele. Ekspresi lambda menyediakan alternatif yang ringkas:
int factor = 3;
std::transform(nums.begin(), nums.end(), result.begin(),
[factor](int x) { return x * factor; });Sintaks lambda adalah [capture](parameters) { body }. Klausa capture menentukan variabel di luar mana yang dapat diakses lambda. Gunakan [=] untuk menangkap semua variabel berdasarkan nilai, [&] untuk menangkap semua variabel berdasarkan referensi, atau cantumkan variabel tertentu seperti [factor] atau [&factor].
Lambdas sangat berguna untuk operasi sekali pakai dengan algoritma seperti pengurutan menggunakan kriteria khusus:
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); });
// Diurutkan berdasarkan nilai mutlak: {-1, -2, 5, 8}Tantangan
MudahMari buat kalkulator harga yang menunjukkan cara menggunakan functor dan ekspresi lambda untuk menerapkan berbagai strategi diskon pada harga produk.
Kamu akan mengatur kodemu dalam dua file:
Discounts.h: Definisikan functor diskon dan fungsi utilitasmu di sini.Buat functor bernama
PercentageDiscountyang menyimpan persentase diskon sebagai bilangan bulat.operator()-nya harus menerima harga bertipedoubledan mengembalikan harga setelah diskon. Misalnya, diskon 20% untuk $100 harus menghasilkan $80.Buat functor lain bernama
FixedDiscountyang menyimpan jumlah tetap yang akan dikurangi, bertipedouble.operator()-nya harus menerima harga dan mengembalikan harga dikurangi jumlah tetap tersebut, tetapi hasilnya tidak boleh kurang dari 0.Buat fungsi bernama
printPricesyang menerimaconst std::vector<double>&dan mencetak semua harga yang dipisahkan oleh spasi, diikuti baris baru. Format setiap harga dengan dua angka di belakang koma.main.cpp: Baca lima input, masing-masing pada baris terpisah:- Harga produk pertama (double)
- Harga produk kedua (double)
- Harga produk ketiga (double)
- Persentase diskon yang diterapkan (bilangan bulat, misalnya 20 untuk 20%)
- Jumlah diskon tetap (double)
Buat vector berisi ketiga harga tersebut dan tunjukkan kedua pendekatan:
- Cetak
Original prices:diikuti harga-harganya - Gunakan
std::transformdengan functorPercentageDiscount-mu untuk membuat vector baru yang berisi harga setelah diskon. CetakAfter percentage discount:diikuti hasilnya - Gunakan
std::transformdengan functorFixedDiscount-mu pada harga asli untuk membuat vector lain. CetakAfter fixed discount:diikuti hasilnya - Gunakan
std::transformdengan ekspresi lambda yang menggandakan setiap harga asli. CetakPremium prices (doubled):diikuti hasilnya - Gunakan
std::sortdengan lambda untuk mengurutkan harga asli secara menurun. CetakSorted (high to low):diikuti harga yang sudah diurutkan
Misalnya, dengan input 100.00, 50.00, 75.00, 20, dan 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 Tantangan ini memungkinkan kamu membandingkan functor, yang mempertahankan state seperti jumlah diskon, dengan lambda, yang menangkap variabel untuk operasi singkat langsung di tempat. Keduanya dapat digunakan dengan lancar bersama algoritma STL seperti std::transform dan std::sort.
Coba sendiri
#include <iostream>
#include <vector>
#include <algorithm>
#include "Discounts.h"
int main() {
// Baca input
double price1, price2, price3;
int percentageDiscount;
double fixedDiscount;
std::cin >> price1;
std::cin >> price2;
std::cin >> price3;
std::cin >> percentageDiscount;
std::cin >> fixedDiscount;
// Buat vector berisi ketiga harga
std::vector<double> prices = {price1, price2, price3};
// TODO: Cetak "Original prices:" lalu cetak harga menggunakan printPrices
// TODO: Gunakan std::transform dengan functor PercentageDiscount
// Buat vector baru untuk hasilnya
// Cetak "After percentage discount:" lalu cetak hasilnya
// TODO: Gunakan std::transform dengan functor FixedDiscount pada harga asli
// Buat vector baru untuk hasilnya
// Cetak "After fixed discount:" lalu cetak hasilnya
// TODO: Gunakan std::transform dengan lambda yang menggandakan setiap harga asli
// Buat vector baru untuk hasilnya
// Cetak "Premium prices (doubled):" lalu cetak hasilnya
// TODO: Gunakan std::sort dengan lambda untuk mengurutkan harga asli dari yang tertinggi ke terendah
// Cetak "Sorted (high to low):" lalu cetak harga yang sudah diurutkan
return 0;
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Object
1Dasar-Dasar OOP
File EksternalBuild dan Kompilasi C++File Header dan File SourceNamespace dan CakupanPengantar OOP dalam C++class vs objectPointer 'this'method (Fungsi Anggota)Atribut (Anggota Data)Dasar Ctor dan DtorRingkasan: Kalkulator Sederhana4Properti class
Anggota instance vs staticGetter dan setterFungsi anggota constKata kunci mutableMethod dan variabel staticFungsi dan class friendRangkuman, Pengelola Rekening Bank7Pewarisan
Pewarisan DasarTingkat Akses pada PewarisanUrutan Pemanggilan Ctor & DtorPenimpaan methodFungsi Virtual & VTablePewarisan BergandaPewarisan VirtualRangkuman: Hierarki Karyawan10Gambaran Umum STL
Gambaran Umum dan Filosofi STLKontainer STLIteratorAlgoritma STLFunctor dan Ekspresi LambdaRangkuman: Frekuensi Kata2Manajemen Memori
Memori Stack vs HeapPointer dan ReferenceMemori Dinamis (new/delete)Smart Pointer di C++RAII di C++Rangkuman: Pengelola Array Dinamis5Enkapsulasi
Penentu Akses dalam C++Penentu Akses secara MendalamPenyembunyian Informasistruct vs classNested dan Inner classRangkuman, Sistem Catatan Siswa8Polimorfisme
Polimorfisme saat Compile vs RuntimeOverloading FungsiMeninjau Kembali Fungsi VirtualFungsi Virtual MurniKelas AbstrakDesain Interface di C++Casting Dinamis & RTTIRangkuman: Kalkulator Bentuk3Konstruktor & Destruktor
Konstruktor DefaultKonstruktor BerparameterKonstruktor SalinKonstruktor PindahDaftar Inisialisasi KonstruktorKonstruktor DelegasiKupas Tuntas DestruktorAturan Tiga, Lima, dan NolRangkuman: class String6Overloading Operator
Pengantar Overloading OperatorOverloading Operator AritmetikaOverloading Operator PerbandinganOperator StreamOverloading Operator PenugasanOverloading Operator [] dan ()Operator Konversi TipeRingkasan, class Matrix9Template
Template FungsiTemplate classSpesialisasi TemplateTemplate VariadikDasar SFINAE & Type TraitsRangkuman, Container GenerikLatihan sendiri: Compiler C++ online