Konudaki soru oldukça yaygın bir karışıklık olduğunu gösteriyor. Karışıklık yeterince yaygın, C ++ SSS'nin özel sanalları kullanmaya karşı uzun zamandır savunması, çünkü karışıklık kötü bir şey gibi görünüyordu.
İlk önce karışıklıktan kurtulmak için: Evet, türetilmiş sınıflarda özel sanal işlevler geçersiz kılınabilir. Türetilmiş sınıfların yöntemleri, temel sınıftan sanal işlevleri çağıramaz, ancak onlar için kendi uygulamalarını sağlayabilirler. Temel sınıfta genel sanal olmayan arabirime ve türetilmiş sınıflarda özelleştirilebilen özel bir uygulamaya sahip Herb Sutter'e göre, "arabirimin belirtiminin, uygulamanın özelleştirilebilir davranışının belirtiminden daha iyi ayrılmasına" olanak tanır. "Sanallık" makalesinde daha fazla bilgi bulabilirsiniz .
Bununla birlikte, sunduğunuz kodda, bence daha fazla ilgiyi hak eden daha ilginç bir şey var. Ortak arabirim, aşırı yüklenmiş sanal olmayan işlevlerden oluşur ve bu işlevler, genel olmayan, aşırı yüklenmemiş sanal işlevleri çağırır. C ++ dünyasında her zamanki gibi bir deyim, bir adı var ve elbette faydalı. Adı (sürpriz, sürpriz!)
"Herkese Açık Aşırı Yüklenen Sanal Olmayanlar Korumalı Aşırı Yüklenmemiş Sanalları Arayın"
Gizleme kuralını düzgün bir şekilde yönetmeye yardımcı olur . Burada daha fazla bilgi edinebilirsiniz , ancak kısaca açıklamaya çalışacağım.
Engine
Sınıfın sanal işlevlerinin de onun arayüzü olduğunu ve saf sanal olmayan aşırı yüklenmiş bir dizi işlev olduğunu hayal edin . Eğer saf sanal olsaydı, yine de aşağıda açıklananla aynı problemle karşılaşabilir, ancak sınıf hiyerarşisinde daha düşük olabilir.
class Engine
{
public:
virtual void SetState( int var, bool val ) {/*some implementation*/}
virtual void SetState( int var, int val ) {/*some implementation*/}
};
Şimdi, türetilmiş bir sınıf oluşturmak istediğinizi ve yalnızca yöntem için iki ints bağımsız değişken olarak alan yeni bir uygulama sağlamanız gerektiğini varsayalım.
class MyTurbochargedV8 : public Engine
{
public:
// To prevent SetState( int var, bool val ) from the base class,
// from being hidden by the new implementation of the other overload (below),
// you have to put using declaration in the derived class
using Engine::SetState;
void SetState( int var, int val ) {/*new implementation*/}
};
Kullanım bildirimini türetilmiş sınıfa koymayı (veya ikinci aşırı yüklemeyi yeniden tanımlamayı) unutursanız, aşağıdaki senaryoda sorun yaşayabilirsiniz.
MyTurbochargedV8* myV8 = new MyTurbochargedV8();
myV8->SetState(5, true);
Engine
Üyelerin gizlenmesini engellemediyseniz , ifade:
myV8->SetState(5, true);
çağırır void SetState( int var, int val )
dönüştürme, türetilmiş sınıftan true
için int
.
Arayüz sanal değilse ve sanal uygulama herkese açık değilse, örneğin exmaple'ınızda, türetilmiş sınıfın yazarının düşünmesi gereken daha az sorunu vardır ve sadece yazabilir
class MyTurbochargedV8 : public Engine
{
private:
void SetStateInt(int var, int val ) {/*new implementation*/}
};