Sanal yıkıcı, temel sınıfta virtual anahtar kelimesi ile tanımlanan bir yıkıcıdır. Bu, temel sınıf üzerinden bir nesne silindiğinde türetilmiş sınıfın yıkıcısının çağrılmasını garanti eder.
class Base { public: virtual ~Base() { /* ... */ } }; class Derived : public Base { public: ~Derived() override { /* ... */ } }; Base* ptr = new Derived(); delete ptr; // Her iki yıkıcı da çağrılır
Sanal yıkıcı olmadan, davranış hatalı olabilir - türetilmiş sınıfın yıkıcısı çağrılmayacak ve bu kaynak sızıntısına yol açacaktır!
Eğer temel sınıfınızda hiç sanal fonksiyon yoksa, yıkıcıyı sanal olarak bildirmek gerekli mi?
Cevap: Evet, sınıfın miras alınması ve temel tür üzerindeki işaretçi ile silinmesi öngörülüyorsa. Diğer sanal fonksiyonlar olmasa bile, türevlerin doğru bir şekilde silinmesi için yıkıcının sanallığı gereklidir.
class Shape { public: virtual ~Shape() {} };
Hikaye 1
Büyük bir grafik kütüphanesi projesinde, temel sınıf üzerinden nesne silindiğinde OpenGL kaynakları (önbellekler, dokular) sızılıyordu - ilgili serbest bırakmalar türetilmiş sınıfların yıkıcılarında bulunuyordu ve bunlar çağrılmıyordu.
Hikaye 2
TCP protokolü için bir ağ kütüphanesinde, oturumlar silindiğinde mirasçıların yıkıcısı çağrılmadı, bu da soketlerin kitlenmesine ve tanımlayıcı limitlerinin tükenmesine yol açtı.
Hikaye 3
C++ ile gömülü bir sistemde yanlış tanımlanmış (sanal olmayan) temel sınıf yıkıcısı, giriş-çıkış denetleyicilerinin sistem kaynakları için bellek sızıntısına neden oldu, cihazlar sürücü güncellemeleri döngüsü sonrasında bozuldu.