C++'da Sanal Yıkıcı

C Da Sanal Yikici



C++, programlamanın temel kavramlarını temellendirmek için kullanılan ve programcıların mantıksal düşünmesini güçlü kılan dildir. C++'da, OOP, sınıfların nesnelerini yaratan Nesne Yönelimli bir dil olduğundan, OOP hayati bir rol oynar. OOP'de sınıfları ve nesneleri inceliyoruz. Sınıflar, farklı türde değişkenler ve farklı üye işlevleri olan veri üyelerini içerir. Örneklerin yardımıyla, herhangi bir sınıfın verilerine erişiriz. Sınıfı oluşturduğunuzda her sınıfın yapıcısı ve yıkıcısı vardır. Yapıcı, o sınıfın nesnesi oluşturulduğunda kendisi olarak adlandırılır. Yapıcı içindeki bir sınıfın değişkenlerini de başlatabiliriz. Yıkıcılar da yapıcı ile birlikte otomatik olarak oluşturulur ancak yıkıcılar nesneyi yok eder ve nesneyi yok etmeden önce çağrılan son işlevdir. Sınıfın adı, örneğin “Meslek” sınıfı oluşturulur. Yapıcısı Profession()'dur ve yıkıcı ~Profession()'dur. Üçünün de adı aynı.

OOP, yapıcılar ve yıkıcılardan bahsettikten sonra şimdi sanal yıkıcılardan bahsedelim. Sanal yıkıcılar, adından da anlaşılacağı gibi, nesneyi yok eder. Bir temel sınıfımız ve bu temel sınıftan türetilmiş bir türetilmiş sınıfımız var. Her iki sınıfın da yapıcıları ve yıkıcıları vardır. Sanal yıkıcı, 'virtual' anahtar kelimesiyle bir temel sınıf işaretçisi kullanarak türetilmiş sınıfın nesnelerini silerken, türetilmiş sınıf nesnesi aracılığıyla tahsis edilen anımsamayı serbest bırakır.

Sanal Yıkıcıyı Neden Kullanıyoruz?

Sınıf üyesi işlevlerin yürütülmesi tamamlandığında veya main() yönteminin yürütülmesi sona ermek üzereyken, nesne oluşturma sırasında ayrılan belleği boşaltmak için yıkıcı otomatik olarak çağrılır. Şimdi, neden sanal bir yok edici kullanıyoruz? Türetilen sınıfı işaret eden temel sınıf silindiğinde, burada işaretçi (*) kullanılır. Temel sınıf yıkıcısı yalnızca bu işlem sırasında çağrılır. Türetilmiş sınıf yıkıcısı çağrılmaz, bu da sorunlara yol açar. Bunlardan biri bellek sızıntısı sorunudur. Bu sorunu önlemek ve kodumuzu güvenli hale getirmek için, temel sınıf yıkıcısını silerek nesnelerin oluşturulması sırasında ayrılan bellek alanını boşaltmak için nesneleri sanal olarak yok ediyoruz.

Sanal Yıkıcı Olmadan C++ Temel Örneği

İmleci silen basit bir program ile programın sanal bir yıkıcı olmadan nasıl çalıştığını görelim.

kod:

#include

ad alanı std'sini kullanma ;
sınıf Ebeveyn_Sınıfı0
{
halka açık :
Ebeveyn_Sınıfı0 ( )
{ cout << 'Ana Sınıf Oluşturucu' << son ; }
~Ebeveyn_Sınıfı0 ( )
{ cout << 'Ebeveyn Sınıfı Yıkıcı' << son ; }
} ;
Child_1 sınıfı : genel Ebeveyn_Sınıfı0
{
halka açık :
Child_1 ( )
{ cout << 'Çocuk Sınıfı Oluşturucu' << son ; }
~Çocuk_1 ( )
{ cout << 'Çocuk Sınıfı Yıkıcı' << son ; }
} ;
int ana ( )
{
Ebeveyn_Sınıfı0 * Işaretçi = yeni Child_1 ( ) ;
işaretçiyi sil ;
geri dönmek 0 ;
}

Bu kod, kodun sanal bir yıkıcı olmadan nasıl yürütüldüğünü açıklar. Her şeyden önce, ebeveyn sınıfı olacak “Parent_Class0” adında bir sınıf oluşturun. Bu sınıfın içinde bir yapıcı ve yıkıcı oluşturun. Bildiğimiz gibi, yapıcı ve yıkıcı, sınıfla aynı şekilde adlandırılır. Yıkıcı, yapıcıya benzer şekilde temsil edilir, ancak onu yapıcıdan ayıran bir simgeye (~) sahiptir. Yapıcı ve yıkıcı içinde, “cout<<” kullanarak bir mesaj yazdırın. Şimdi, 'Child_1' olan başka bir sınıf oluşturun. Bu sınıf, 'Parent_Class0' üst sınıfından türetilmiştir. Türetilmiş sınıfın, çıktı ekranına yazdırılacak bir mesaj içeren yapıcısı ve yıkıcısı vardır.

main() yönteminde, bir “Parent_Class0” örneği oluşturur ve ona türetilmiş bir sınıf atarız. Bu durumda hatırlanması gereken en önemli nokta, üst sınıfı almak için bir işaretçi kullanmamızdır. Ana sınıfın içine girdiğinde, ana sınıf yapıcısını yürütür. Ardından alt sınıfa gider ve yapıcısını çalıştırır. Alt sınıfın yıkıcısını çalıştırmadan önce, üst sınıfın yıkıcısını yürütmesi gerekir. Derleyici, ana sınıfın yıkıcısını yürütür ve bir alt sınıfın yıkıcısını yürütmeden sınıfı sonlandırır. Sorun bu; çocuğun sınıfının hafızasını boşaltmaz. Bir üst sınıfın yapıcısını, bir alt sınıfın yapıcısını ve bir üst sınıfın yıkıcısını temsil eder. Bu, bir alt sınıfın yıkıcısının yürütülmediğini gösterir. Bu yürütmeden sonra, main() işlevindeki işaretçiyi sileriz.

Çıktı:

Virtual Destructor ile C++ Örneği

Sanal yok edici ile ve sanal yok edici olmadan nasıl çalıştığını ayırt etmek için sanal yok ediciyi basit bir kodla tartışalım.

kod:

#include

ad alanı std'sini kullanma ;
sınıf Ebeveyn_Sınıfı0
{
halka açık :
Ebeveyn_Sınıfı0 ( )
{ cout << 'Ana Sınıf Oluşturucu' << son ; }
sanal ~Parent_Class0 ( )
{ cout << 'Ebeveyn Sınıfı Yıkıcı' << son ; }
} ;
Child_1 sınıfı : genel Ebeveyn_Sınıfı0
{
halka açık :
Child_1 ( )
{ cout << 'Çocuk Sınıfı Oluşturucu' << son ; }
sanal ~Child_1 ( )
{ cout << 'Çocuk Sınıfı Yıkıcı' << son ; }
} ;
int ana ( )
{
Ebeveyn_Sınıfı0 * Işaretçi = yeni Child_1 ( ) ;
işaretçiyi sil ;
geri dönmek 0 ;
}

İlk program, karşılaştığımız sorunu sanal bir yıkıcı olmadan açıkladı. Şimdi, bu kod sanal bir yıkıcı kullanarak bu sorunu çözecektir. İlk olarak, ilk kodu kopyalayın ve bu programda iki yere sadece bir anahtar kelime ekleyin. Bu kelime 'sanal' dır. Bu kelimeyi üst sınıfın yıkıcısı olan 'Parent_Class0' ile birlikte ekleyin. Benzer şekilde, ebeveyn sınıftan türetilen “Child_1” olan alt sınıfın yıkıcısı ile bunu belirtin. Bu 'virtual' anahtar sözcüğü küçük bir değişiklik yapar ve önce 'Child_1' alt sınıfının yıkıcısını çalıştırır. Ardından, 'Parent_Class0' adlı üst sınıfın yıkıcısını yürütür. Programın geri kalanı, sanal bir yıkıcı olmadan çalıştığı gibi çalışır. Bu küçük kod parçasını ekleyerek hafızamızı sızıntıdan kurtarabiliriz. Şimdi, konsolda dört mesaj görüntüler. İlk olarak, bir üst sınıfın yapıcısı, ardından bir alt sınıfın yapıcısı, bir alt sınıfın yıkıcısı ve bir üst sınıfın yıkıcısı. Sonunda, main() yöntemi içindeki işaretçiyi sileriz.

Çıktı:

C++ Saf Sanal Yıkıcı Örneği

Bu kodda, saf sanal yıkıcıdan, nasıl çalıştığından ve sanal bir yıkıcıdan ne kadar farklı olduğundan bahsedeceğiz.

kod:

#include

sınıf Ebeveyn_0 {
halka açık :
sanal ~Ebeveyn_0 ( ) = 0 ;
} ;
ebeveyn_0 :: ~Ebeveyn_0 ( )
{
std :: cout << 'Merhaba Ben Pure Destructor. Beni Aradınız!' ;
}
Child_0 sınıfı : genel Ebeveyn_0 {
halka açık :
~Çocuk_0 ( ) { std :: cout << 'Türetilmiş yıkıcı burada \n ' ; }
} ;

int ana ( )
{
ebeveyn_0 * ptr_0 = yeni Child_0 ( ) ;
ptr_0'ı sil ;
geri dönmek 0 ;
}

Kodun ilk adımında 'Parent_0' üst sınıfı oluşturulur. İçinde, sanal üst yıkıcıyı oluşturun ve 0 ile atayın. Bu, sanal yok ediciyi saf sanal yok ediciye ayarlar, bu da üst sınıfın artık soyut olduğu ve bu sınıfın örneklerini oluşturamayacağımız anlamına gelir. 'Parent_0' üst sınıfının dışında, yıkıcıları ve std::cout'u tanımlayın. Gerekli metin std::cout kullanılarak gösterilir. Ardından, üst sınıftan bir “Child_0” sınıfı türetin ve onun yıkıcısını tanımlayın. Yıkıcının içinde bir mesaj yazdırın. main() işlevinde, üst sınıfın işaretçisini oluşturun ve alt sınıfı ona atayın.

Derleyici, 'Parent_0' üst sınıfına gider. İşaretçi oluşturulduğunda, yapıcısı otomatik olarak çağrılır. Ardından derleyici, yapıcısını çağırmak için alt sınıfa gider. Yapıcı başarılı bir şekilde yürütüldükten sonra, 'Child_0' alt sınıfının yıkıcısını yürütür. Ardından, bir üst sınıfın yıkıcısını yürütür. Bu şekilde, saf bir sanal yıkıcı yapabiliriz. Kullanması teşvik edilmez çünkü bu yöntemi kullanarak, ana sınıf soyut hale gelir ve bu da onu işe yaramaz hale getirir. En çok kullanılan metodoloji sanal yok edicidir ve iyi bir uygulamadır.

Çıktı:

Çözüm

OOP kavramından başlayarak yapıcılara ve yıkıcılara doğru ilerleyen sanal yıkıcıyı öğrendik. Tüm bunları anlattıktan sonra virtual destructor konusunu kodlama örnekleri ve pure virtual destructor ile detaylı bir şekilde ele aldık. Sanal yıkıcıyı açıklamadan önce yapıcılar, yıkıcılar ve kalıtım hakkında bilgi sahibi olmalıyız. Kalıtımda, sınıfları bir üst sınıftan miras alırız. Alt sınıflar birden fazla olabilir ancak üst sınıf yalnızca bir tanedir. Bellek sızıntısından kurtarmak için kalıtımda sanal yıkıcılar ve saf sanal yıkıcılar uygulanır. Temel örnekten gelişmiş örneğe kadar, kullanmaya başlamak ve türetilmiş sınıfın belleğini sanal olarak yok etmek için bilmeniz gereken her şeyi ele aldık.