Metot Geçersiz Kılma
Coddy'nin C++ Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 51 / 104.
Metot geçersiz kılma, türetilmiş bir sınıfın temel sınıfta zaten bulunan bir metot için kendi uygulamasını sağlamasıyla gerçekleşir. Bu, türetilmiş sınıfların aynı metot imzasını korurken devralınan davranışı özelleştirmesine olanak tanır.
Bir yöntemi geçersiz kılmak için türetilmiş sınıfta aynı ada, dönüş türüne ve parametrelere sahip bir yöntem tanımlaman yeterlidir:
class Animal {
public:
void speak() {
std::cout << "Some sound" << std::endl;
}
};
class Dog : public Animal {
public:
void speak() {
std::cout << "Woof!" << std::endl;
}
};
Dog d;
d.speak(); // Çıktı: Woof!Türetilmiş sınıf versiyonu temel sınıf versiyonunu gizler. Ancak, kapsam çözünürlük operatörünü kullanarak temel sınıf metoduna hala erişebilirsiniz:
class Dog : public Animal {
public:
void speak() {
Animal::speak(); // Temel sınıf versiyonunu çağır
std::cout << "Woof!" << std::endl;
}
};Bu temel geçersiz kılma (overriding) biçiminde önemli bir sınırlama vardır. Türetilmiş bir nesneye bir temel sınıf işaretçisi veya referansı aracılığıyla eriştiğinizde, bunun yerine temel sınıf sürümü çağrılır:
Dog d;
Animal* ptr = &d;
ptr->speak(); // Çıktı: Some sound (not Woof!)Bu durum, derleyicinin hangi metodun çağrılacağını gerçek nesne türüne göre değil, işaretçi türüne göre belirlemesi nedeniyle gerçekleşir. Doğru metodun gerçek nesneye dayalı olarak çağrıldığı gerçek çalışma zamanı polimorfizmini elde etmek için, bir sonraki derste ele alacağımız sanal fonksiyonlara ihtiyacınız olacak.
Görev
KolayYöntem geçersiz kılmayı uygulamalı olarak gösteren bir bildirim sistemi oluşturalım. Bir temel Notifier sınıfı ve iletilerin nasıl gönderileceğini özelleştiren iki özel bildirim sınıfı oluşturacaksın.
Kodunu üç dosyaya ayıracaksın:
Notifier.h: Şunları içeren bir temelNotifiersınıfı tanımla:- Protected bir
std::string recipientüyesi - Bir alıcı adı alan ve bunu kaydeden bir oluşturucu
- Şunu yazdıran bir public
send(const std::string& message)yöntemi:Sending to <recipient>: <message>
- Protected bir
EmailNotifier.h:EmailNotifiersınıfından public olarak türeyen birNotifiersınıfı tanımla:- Bir alıcı alan ve bunu temel sınıfa aktaran bir oluşturucu
- Önce
send()kullanarak temel sınıf sürümünü çağıran, ardındanNotifier::send()yazdıran[Email sent successfully]yöntemini geçersiz kıl
main.cpp: İki girdi oku (her biri ayrı bir satırda):- Alıcı adı (string)
- İleti içeriği (string)
SMSNotifiersınıfından public olarak türeyen birNotifiersınıfını doğrudan main.cpp içinde tanımla:- Bir alıcı alan ve bunu temel sınıfa aktaran bir oluşturucu
- Temel davranışı çağırmadan tamamen değiştirecek şekilde şunu yazdıran
send()yöntemini geçersiz kıl:SMS to <recipient>: <message>
Aynı alıcıyı kullanarak her bildirim türünden (temel
Notifier,EmailNotifierveSMSNotifier) birer nesne oluştur. Girdi iletisiyle her biri üzerindesend()çağrısı yap ve her birinin arasına bir ayraç satırı yazdır:--- Base Notifier --- <output> --- Email Notifier --- <output> --- SMS Notifier --- <output>
Örneğin, girdiler Alice ve Hello there! olduğunda:
--- Base Notifier ---
Sending to Alice: Hello there!
--- Email Notifier ---
Sending to Alice: Hello there!
[Email sent successfully]
--- SMS Notifier ---
SMS to Alice: Hello there!EmailNotifier sınıfının önce üst sınıf yöntemini çağırarak temel davranışı nasıl genişlettiğine, SMSNotifier sınıfının ise bunu kendi uygulamasıyla tamamen değiştirdiğine dikkat et. Header guard'larını eklemeyi ve her dosyaya uygun başlık dosyalarını dahil etmeyi unutma.
Kendin dene
#include <iostream>
#include <string>
#include "Notifier.h"
#include "EmailNotifier.h"
using namespace std;
// TODO: Burada Notifier sınıfından genel (public) olarak miras alan SMSNotifier sınıfını tanımlayın
// - Alıcıyı (recipient) temel sınıfa (base class) ileten kurucu metot (constructor)
// - Şunu yazdırmak için send() metodunu geçersiz kılın (override): SMS to <recipient>: <message>
// (temel davranışı tamamen değiştirin, üst sınıfın send() metodunu çağırmayın)
int main() {
string recipient;
string message;
getline(cin, recipient);
getline(cin, message);
// TODO: recipient ile Notifier nesnesi oluşturun
// "--- Base Notifier ---" yazdırın
// message ile send() metodunu çağırın
// TODO: recipient ile EmailNotifier nesnesi oluşturun
// "--- Email Notifier ---" yazdırın
// message ile send() metodunu çağırın
// TODO: recipient ile SMSNotifier nesnesi oluşturun
// "--- SMS Notifier ---" yazdırın
// message ile send() metodunu çağırın
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