Saf Sanal Fonksiyonlar
Coddy'nin C++ Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 59 / 104.
Saf sanal işlev, temel sınıfta uygulaması bulunmayan bir sanal işlevdir. İşlev bildirimine = 0 atanarak bildirilir. Bu, derleyiciye türetilmiş sınıfların kendi uygulamalarını zorunlu olarak sağlaması gerektiğini bildirir.
class Shape {
public:
virtual double area() = 0; // Saf sanal fonksiyon
virtual ~Shape() = default;
};Varsayılan bir davranış sağlayan normal sanal function’ların aksine, saf sanal function’lar bir sözleşme tanımlar: herhangi bir somut türetilmiş class’ın örneği oluşturulabilmek için bu function’ı uygulaması gerekir. Temel class yalnızca ne yapılması gerektiğini, nasıl yapılacağını değil, bildirir.
class Circle : public Shape {
double radius;
public:
Circle(double r) : radius(r) {}
double area() override {
return 3.14159 * radius * radius;
}
};
class Rectangle : public Shape {
double width, height;
public:
Rectangle(double w, double h) : width(w), height(h) {}
double area() override {
return width * height;
}
};Hem Circle hem de Rectangle, Shape içinde saf sanal olduğu için area() işlevini uygulamalıdır. Türetilmiş bir sınıf tüm saf sanal işlevleri uygulamazsa o da soyut hâle gelir ve örneği oluşturulamaz.
Saf sanal işlevler, temel sınıf anlamlı bir varsayılan uygulama sağlayamadığında gereklidir. Her şeklin bir alanı vardır, ancak belirli şekil türünü bilmeden “genel şekil alanını” hesaplamanın mantıklı bir yolu yoktur.
Görev
KolayFarklı ödeme yöntemleri arasında saf sanal işlevlerin bir sözleşmeyi nasıl zorunlu kıldığını gösteren bir ödeme işleme sistemi oluşturalım. Tüm ödeme işlemcilerinin ne yapması gerektiğini tanımlayan soyut bir temel sınıf oluşturacak, ardından bu sözleşmeyi yerine getiren somut ödeme türlerini uygulayacaksınız.
Kodunuzu üç dosya arasında düzenleyeceksiniz:
PaymentProcessor.h: Tüm ödeme yöntemleri için şablon görevi gören soyut birPaymentProcessorsınıfı tanımlayın. Bu sınıf şunlara sahip olmalıdır:- Korumalı bir
std::string accountIdüyesi - Hesap kimliğini başlatan bir oluşturucu
- Saf sanal bir
processPayment(double amount)yöntemi: her ödeme türü bunu farklı şekilde uygulamalıdır getProcessorName()döndüren saf sanal birstd::stringyöntemi- Sanal bir yok edici
- Korumalı bir
PaymentMethods.h:PaymentProcessor'dan kalıtım alan iki somut ödeme işlemcisi uygulayın:CreditCardProcessor:- Özel bir
double feePercentageüyesi (işlem ücreti oranı) - Hesap kimliği ve ücret yüzdesi alan bir oluşturucu
- Ücreti (amount * feePercentage / 100) hesaplamak ve ardından şunu yazdırmak için
processPayment()yöntemini uygulayın:Credit Card [<accountId>]: Charged $<amount> (Fee: $<fee>) getProcessorName()döndürecek şekilde"CreditCard"yöntemini uygulayın
BankTransferProcessor:- Özel bir
std::string bankNameüyesi - Hesap kimliği ve banka adı alan bir oluşturucu
- Şunu yazdırmak için
processPayment()yöntemini uygulayın:Bank Transfer [<accountId>] via <bankName>: Transferred $<amount> getProcessorName()döndürecek şekilde"BankTransfer"yöntemini uygulayın
- Özel bir
main.cpp: Dört girdi okuyun (her biri ayrı bir satırda):- Kredi kartı hesap kimliği
- Kredi kartı ücret yüzdesi (double)
- Banka hesap kimliği
- Banka adı
Her iki ödeme işlemcisini oluşturun ve bunları
PaymentProcessor*işaretçilerinden oluşan bir dizide saklayın. Her işlemciden100.0tutarında bir ödeme geçirin ve her işlemden önce işlemci adını görüntüleyin:Processing with <processorName>: <processPayment output>İşlemciler arasında boş bir satır yazdırın. İşiniz bittiğinde dinamik olarak ayrılmış nesneleri temizleyin.
Örneğin CC-4521, 2.5, BA-7890 ve National Bank girdileriyle:
Processing with CreditCard:
Credit Card [CC-4521]: Charged $100 (Fee: $2.5)
Processing with BankTransfer:
Bank Transfer [BA-7890] via National Bank: Transferred $100PaymentProcessor saf sanal işlevlere sahip olduğundan, onu doğrudan örnekleyemezsiniz: yalnızca sözleşmeyi yerine getiren somut uygulamalar oluşturulabilir. Bu, her ödeme yönteminin kendine özgü işleme mantığını sağlamasını garanti eder.
Kendin dene
#include <iostream>
#include <string>
#include "PaymentMethods.h"
using namespace std;
int main() {
// Girdileri oku
string ccAccountId;
double feePercentage;
string bankAccountId;
string bankName;
getline(cin, ccAccountId);
cin >> feePercentage;
cin.ignore();
getline(cin, bankAccountId);
getline(cin, bankName);
// TODO: 2 elemanlı bir PaymentProcessor* işaretçi dizisi oluştur
// TODO: CreditCardProcessor ve BankTransferProcessor nesneleri oluştur
// ve bunları diziye yerleştir
// TODO: Diziyi döngüyle gez ve her işlemci için:
// 1. Print "Processing with <processorName>:"
// 2. processPayment'ı 100.0 tutarıyla çağır
// 3. İşlemciler arasında boş bir satır yazdır (sonuncudan sonra değil)
// TODO: Dinamik olarak ayrılmış nesneleri temizle
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