miras
Kalıtımın bütün noktası, türetilmiş bir sınıfın bir örneğinin, türetilmiş herhangi bir türden herhangi bir diğer örneğe aynı şekilde muamele edilebileceği şekilde birçok farklı uygulama arasında ortak bir arayüz ve protokol paylaşmaktır.
C ++ 'da miras uygulama detaylarını beraberinde getirir, yıkıcıyı sanal olarak işaretlemek (veya işaretlememek) böyle bir uygulama detayıdır.
İşlev Bağlama
Şimdi bir fonksiyon veya bir kurucu ya da yıkıcı gibi özel durumları çağrıldığında, derleyici hangi fonksiyon uygulamasının kastedildiğini seçmelidir. Daha sonra bu amacı izleyen makine kodu üretmelidir.
Bunu yapmanın en basit yolu, işlevi derleme zamanında seçmek ve herhangi bir değerden bağımsız olarak, bu kod parçası yürütüldüğünde, her zaman işlevin kodunu çalıştırması için yeterli makine kodu yaymak olacaktır. Bu, kalıtım dışında harika çalışıyor.
Bir fonksiyona sahip bir temel sınıfımız varsa (yapıcı veya yıkıcı dahil herhangi bir fonksiyon olabilir) ve kodunuz üzerinde bir fonksiyon çağırıyorsa, bu ne anlama geliyor?
Örneğinizden initialize_vector()
, derleyiciyi çağırdıysanız, bulunan uygulamayı Base
veya bulunan uygulamayı gerçekten çağırmak isteyip istemediğinize karar vermesi gerekir Derived
. Buna karar vermenin iki yolu vardır:
- Birincisi, bir
Base
türden aradığınız için uygulamada demek istediğinize karar vermektir Base
.
- İkincisi,
Base
yazılan değerde saklanan değerin çalışma zamanı türünün olabileceği Base
veya Derived
hangi çağrının yapılacağına ilişkin kararın çağrıldığında (her çağrıldığında) çalışma zamanında yapılması gerektiğine karar vermektir .
Bu noktada derleyici karıştırılır, her iki seçenek de eşit derecede geçerlidir. Bu, virtual
karışıma geldiğinde. Bu anahtar kelime bulunduğunda, derleyici, kod gerçek bir değerle çalışana kadar tüm olası uygulamalar arasındaki kararı geciktiren seçenek 2'yi seçer. Bu anahtar kelime yoksa, derleyici seçenek 1'i seçer, çünkü bu normal bir davranıştır.
Derleyici, sanal işlev çağrısı durumunda yine de 1. seçeneği seçebilir. Ama sadece bunun her zaman böyle olduğunu kanıtlayabilirse.
Yapıcılar ve Yıkıcılar
Öyleyse neden sanal bir Oluşturucu belirtmiyoruz?
Daha sezgisel nasıl derleyici için yapıcı özdeş uygulamaları arasında alacağını Derived
ve Derived2
? Bu oldukça basit, yapamıyor. Derleyicinin gerçekten neyi amaçladığını öğrenebileceği önceden var olan bir değer yoktur. Önceden var olan bir değer yoktur çünkü kurucunun işi budur.
Öyleyse neden sanal bir yıkıcı belirtmemiz gerekiyor?
Daha sezgisel olarak derleyici Base
ve için uygulamalar arasında nasıl seçim yapar Derived
? Bunlar sadece işlev çağrılarıdır, bu nedenle işlev çağrısı davranışı gerçekleşir. Bildirilen bir sanal yıkıcı olmadan, derleyici Base
, değer çalışma zamanı türünden bağımsız olarak doğrudan yıkıcıya bağlanmaya karar verecektir .
Birçok derleyicide, türetilmiş herhangi bir veri üyesi bildirmez veya başka türlerden miras almazsa, içindeki davranış ~Base()
uygun olacaktır, ancak garanti edilmez. Tamamen ateşlenmemiş bir alev makinesinin önünde durmak gibi, tamamen tesadüfen çalışır. Bir süre iyisin.
C ++ 'da herhangi bir taban veya arabirim türünü bildirmenin tek doğru yolu, sanal bir yıkıcı bildirmektir, böylece bu türün tür hiyerarşisinin belirli bir örneği için doğru yıkıcı çağrılır. Bu, örneğin en fazla bilgisi olan işlevin, o örneği doğru şekilde temizlemesini sağlar.
~derived()
vec'in yıkıcısına delege olan bir dil sağlar . Alternatif olarak,unique_ptr<base> pt
bunun türetilmiş yıkıcıyı bileceğini varsayıyorsunuz . Sanal bir yöntem olmadan durum böyle olamaz. Bir unique_ptr öğesine herhangi bir çalışma zamanı gösterimi olmayan bir şablon parametresi olan bir silme işlevi verilebilir ve bu özellik bu kod için kullanılmaz.