Sorunun Tarihi:
C++'da nesne yönelimli programlamanın desteği eklendi, bu da modern dillerin temelidir. Polimorfizmin gerçekleştirilmesi için sanal fonksiyonlar kullanıldı. Bu, bir yöntemin doğru uygulamasının çalıştırma aşamasında çağrılmasına olanak tanıdı, yalnızca derleme aşamasında değil; bu, miras alınan bir mimari için kritik öneme sahiptir.
Problem:
Yaygın hata, yöntemlerin statik ve dinamik çağrıları arasında karışıklık yaşanması, unutulmuş sanal yıkıcılar ve miras almakla ilgili yanlışlıklardır (örneğin, nesne dilimi, temel sürümün yerine değiştirilmiş (override) sürümün çağrılması). Polimorfizmin gerçekten ne zaman çalıştığı sık sık karıştırılmaktadır.
Çözüm:
Sanal bir fonksiyon, temel sınıfta virtual anahtar kelimesi ile tanımlanır ve türetilmiş sınıfta değiştirilebilir (override). Eğer fonksiyon temel sınıfın işaretçisi veya referansı ile çağrılırsa, türetilmiş sınıftan olan versiyonu çalıştırılır.
Kod Örneği:
struct Base { virtual void foo() { std::cout << "Base::foo "; } }; struct Derived : Base { void foo() override { std::cout << "Derived::foo "; } }; void call(Base& b) { b.foo(); } int main() { Derived d; call(d); // Derived::foo yazdırır }
Ana özellikler:
override anahtar kelimesinin kullanılmasını gerektirir (C++11'den itibaren mümkündür)Bir nesne değer ile aktarıldığında polimorfizm çalışır mı?
Hayır. Değer ile aktarma, "slicing" durumuna yol açar — yalnızca parametre tipine karşılık gelen kısım kopyalanır (genellikle temel sınıf), polimorfizm devre dışı kalır.
Kod örneği:
void call(Base b) { b.foo(); } // her zaman Base::foo çağrısı
Temel sınıfta yıkıcıyı sanal olarak tanımlamak gerekli mi?
Evet, eğer türetilmiş nesnelerin temel sınıf işaretçisi üzerinden silinmesi öngörülüyorsa gereklidir. Aksi halde bellek sızıntısı veya kaynakların kapanmaması meydana gelir.
Kod örneği:
struct Base { virtual ~Base() {} };
Eğer alt sınıfta override anahtar kelimesi kullanılmazsa ne olur?
Eğer türetilmiş sınıfta override belirtilmezse, ancak yanlışlıkla fonksiyonun imzası değiştirilirse (örneğin, const atlanır veya parametrelerde hata yapılırsa), fonksiyon sanal olanı geçersiz kılamaz, yeni bir fonksiyon yaratılır ve polimorfizm beklendiği gibi çalışmaz.
override (eksik override, imzanın değiştirilmesi)Programcı, temel sınıfın yıkıcısını sanal olarak tanımlamamıştır; temel işaretçi üzerinden nesne dizisinin silinmesi bellek sızıntısına yol açmıştır.
Artılar:
Eksiler:
Sanal bir yıkıcı tanımlanmıştır; sadece temel tip üzerinde referanslar/işaretçilerin kullanıldığı durumdur. Polimorfizm doğru çalışmıştır.
Artılar:
Eksiler: