Tarihi:
C++ sınıf mirasını, C++ dilinden ve nesne yönelimli metodolojilerden almıştır. Birden çok miras ve sanal mirasın ortaya çıkması, hiyerarşilerin yapısını karmaşık hale getirerek esnekliği artırmış, ancak yeni hata türlerini de eklemiştir.
Sorun:
Doğrudan miras, bir sınıfın başka bir sınıftan direkt olarak, ek karmaşıklık olmadan miras alması durumudur. Dolaylı miras, miras alınan üyelerin bir veya daha fazla ara miras zinciri aracılığıyla gelmesi durumunda meydana gelir. Ana zorluk "elmas problemi"dir (diamond problem), burada bir temel sınıfa birden fazla yol ile ulaşmak, türetilmiş sınıflarda üyelerin tekrarlanmasına yol açabilir.
Çözüm:
Karmaşıklığı yönetmek için sanal miras kullanılır; bu, hiyerarşide tek bir ortak temel sınıf üyesi sağlarken, her bir zincir için değil.
Kod örneği:
class A { public: int value; }; class B : public virtual A {}; class C : public virtual A {}; class D : public B, public C {};
D sınıfında sadece bir tane A::value üyesi olacaktır.
Anahtar noktalar:
Elmas problemi mevcut olduğunda sanal miras kullanılmadığında belirsiz davranış ortaya çıkabilir mi?
Elmas hiyerarşisinde sanal miras kullanılmadığında, temel sınıf üyeleri tekrarlanır. Bu, kod mantığını karmaşık hale getirebilir ve temel sınıf üyelerine erişimde belirsizlik yaratabilir.
Hangi durumlarda sanal miras kullanmamak gerekir?
Hiyerarşilerinizin elmas yapıyı oluşturmadığından eminseniz veya temel sınıf veri içermiyorsa, sanal miras gerekmez.
Sanal miras durumunda yapıcıların çağrısını nasıl yönetirsiniz?
Sanal temel sınıfın yapıcısı yalnızca en "alt düzey" türetilmiş sınıf tarafından çağrılır. Ara sınıflarda sanal temel sınıf için argüman belirtmek yasaktır (eğer son sınıfta açıkça başlatılmazsa, yapılandırıcı varsayılan olarak çağrılır).
Kod örneği:
class A { public: A(int x) { /* ... */ } }; class B : public virtual A { public: B() : A(0) {} // hata: A'yı burada başlatamazsınız }; class D : public B { public: D() : A(10), B() {} // doğru };
Büyük bir projede geliştirici, elmas yapısının ortaya çıktığını fark etmedi — her iki ara sınıf da doğrudan bir temel sınıftan miras alıyordu. Temel sınıfın bir üyesine erişim belirsizlik yaratıyordu, kod okunaksızdı.
Artılar:
Eksiler:
Mimar sorunu önceden fark etti ve ara sınıflar için sanal miras kullandı; sanal temel sınıfın yapıcısı sadece en alt türetilmiş sınıfta doğru bir şekilde çağrıldı.
Artılar:
Eksiler: