Sorunuzun ifadesine bakarak ("sakla" kelimesini kullandınız), burada neler olduğunu zaten biliyorsunuz. Bu fenomene "isim gizleme" denir. Herhangi bir nedenle, birisi ad gizlemenin neden gerçekleştiği hakkında her soru sorduğunda , yanıt veren kişiler ya "ad gizleme" adını verdiğini söyler ve nasıl çalıştığını (muhtemelen zaten biliyorsunuz) ya da nasıl geçersiz kılacağını açıklar ( hiç sormadı), ama hiç kimse gerçek "neden" sorusunu ele almak umurunda görünmüyor.
Karar, ismin gizlenmesinin ardındaki mantık, yani aslında neden C ++ 'da tasarlandığını, miras alınan aşırı yüklenmiş fonksiyonlar setinin mevcut set ile karışmasına izin verilebilecek belirli mantıksız, öngörülemeyen ve potansiyel olarak tehlikeli davranışlardan kaçınmaktır. verilen sınıfta aşırı yüklenmeler. Muhtemelen C ++ aşırı yük çözünürlüğünün aday setinden en iyi işlevi seçerek çalıştığını biliyorsunuzdur. Bu, argüman türlerini parametre türleriyle eşleştirerek yapılır. Eşleşen kurallar zaman zaman karmaşık olabilir ve genellikle hazırlıksız bir kullanıcı tarafından mantıksız olarak algılanabilecek sonuçlara yol açabilir. Önceden var olan bir dizi gruba yeni işlevler eklemek, aşırı yük çözünürlüğü sonuçlarında oldukça ciddi bir kaymaya neden olabilir.
Örneğin, temel sınıfın tür parametresini alan bir B
üye işlevi foo
olduğunu void *
ve tüm çağrıların foo(NULL)
çözümlendiğini varsayalım B::foo(void *)
. Diyelim ki hiçbir isim saklanmadı ve bu B::foo(void *)
, inen birçok farklı sınıfta görülebilir B
. Ancak, diyelim ki bazı [dolaylı, uzak] soyundan D
sınıfın B
bir işlevi foo(int)
tanımlanmıştır. Şimdi, adı gizleme olmadan D
hem sahiptir foo(void *)
ve foo(int)
görünür ve aşırı yük çözünürlükte katılan. Türdeki foo(NULL)
bir nesne üzerinden yapıldığında , çağrılar hangi işleve çözümlenecektir D
? Çözüleceklerdir D::foo(int)
, çünkü int
integral sıfır için daha iyi bir eştir (ör.NULL
) herhangi bir işaretçi türünden daha fazladır. Yani, hiyerarşi boyunca çağrısındafoo(NULL)
bir işleve giderken D
(içinde ve altında) aniden diğerine giderler.
Başka bir örnek C ++ Tasarım ve Gelişimi , sayfa 77'de verilmiştir:
class Base {
int x;
public:
virtual void copy(Base* p) { x = p-> x; }
};
class Derived{
int xx;
public:
virtual void copy(Derived* p) { xx = p->xx; Base::copy(p); }
};
void f(Base a, Derived b)
{
a.copy(&b); // ok: copy Base part of b
b.copy(&a); // error: copy(Base*) is hidden by copy(Derived*)
}
Bu kural olmadan, b'nin durumu kısmen güncellenerek dilimlemeye yol açar.
Bu davranış, dil tasarlanırken istenmeyen bir durum olarak kabul edildi. Daha iyi bir yaklaşım olarak, "isim gizleme" şartnamesini izlemeye karar verildi, yani her sınıf, beyan ettiği her yöntem adına göre bir "temiz sayfa" ile başlar. Bu davranışı geçersiz kılmak için kullanıcıdan açık bir eylem gereklidir: aslen miras alınan yöntem (ler) in (şu anda kullanımdan kaldırılmış) bir ifadesi, şimdi açık bir kullanım-bildirimi kullanımı.
Orijinal yayında doğru şekilde gözlemlediğiniz gibi ("Polimorfik değil" ifadesine atıfta bulunuyorum), bu davranış sınıflar arasındaki IS-A ilişkisinin ihlali olarak görülebilir. Bu doğrudur, ama görünüşe göre o zamanlar sonunda isim gizlemenin daha az kötülük olacağına karar verildi.