7

It recently came to my attention o üye fonksiyonları serbest fonksiyonlar sınıf içinde aynı adla tamamen gölgesi. Ve tamamen demek istediğim, aynı ada sahip her bir serbest fonksiyonun aşırı yükleme çözünürlüğü için hiç dikkate alınmadığı. Ben böyle somwthing ile bitti neden anlayabiliyorum:Sınıf üyesi neden aynı isimle gölge içermeyen işlevler çalıştırıyor?

işlevleri özdeş imzalara sahip
void f(); 

struct S 
{ 
    void f(); 

    void g() 
    { 
     f(); // calls S::f instead of ::f 
    } 
}; 

, Değişken etki alanı olarak sadece doğal aynı şekilde çalışır. Ben sınıf içinde gelen serbest fonksiyonu gölgeli çağırmak nasıl sormuyorum

void f(); 

struct S 
{ 
    void f(int x); 

    void g() 
    { 
     f(); // fails to compile attempting to call S::f, which has wrong signature 
    } 
}; 

: ücretsiz işlevi aşağıdaki gibi farklı imza sahip olduğu Ama neden unambigious aramalar engellenir. Bilmek istediğim bu tasarımın ardındaki mantıktır.

+1

Bjarne Stroustrup'a sormanız gerekebilir! – peacemaker

+1

Bunun gibi arama, oluşturulan aday işlevlerin listesinin her zaman küçük olduğu anlamına gelir. Derleme zamanları için iyi, tüm olası adayları (ADL dahil) aradıysa ve çok hızlı bir şekilde çok yavaş alacağı birçok şablon bulunduğunu hayal edebilirsiniz. Ayrıca çoğu durumda kullanımı ve istenen semantiği yansıtır. Normalde "foo" dediğinizde, en yakın olan "foo" dır. En yakın olanı değilse, bir hata yapması muhtemeldir. Bir hata, çalışma zamanında gerçekleşen tuhaf şeylerden daha iyidir. Yerel şeyler tutmak iyi bir davranış. – Flexo

+2

Bu sunumun, Name Lookup'da (http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-/Stephan-T-Lavavej-Core-C-1-of -n – MFH

cevap

6

Niteliksiz ad arama için, bir seferde yalnızca bir kapsam göz önünde bulundurulur ve bu kapsamdaki arama sonuç vermezse, bir sonraki daha yüksek kapsam aranır. Sizin durumunuzda sadece S'un kapsamı aranır.

Ama serbest fonksiyonu böyle farklı imza sahip olduğu neden unambigious aramaları engeller:

sorun ad arama, isimleri dışında herhangi bir şeyle tanımlayıcıyı ele almıyor olmasıdır. Bir işlevi çağırmak aslında bir tanımlayıcı görür, aslında tamamen habersizdir. Sadece auto x = f;'u kullanırsanız, aynı ad arama işlemi olur ve bu şekilde düşünürseniz, arama yapmak için çok sınırlı bir kapsamı istediğinizden çok iyi nedenler vardır. Başka bir şey sadece kullanıcıyı şaşırtacaktır.

+1

"_Sorun, adın kendisi ile ilgili bir şeyle değil, adın, identifier._ ile ilgili olmaması." Hemen hemen tüm dillerde, bu doğrudur. C++ 'da değil. – curiousguy

2

Yetkili bir yanıt veremiyorum (Belki bazıları Design and Evolution of C++'dan bir alıntıyı hatırlar ya da o anda komite üzerinde olmuştur), ancak ilk tahminim, gösterdiğiniz gibi, tam olarak başarısız olmaktır. Belirli bir zamanda kaç şeyin kapsama alanı olduğunu unutmak kolaydır. Ek olarak aşırı yük çözünürlüğü oldukça karmaşık olabilir ve varsayılan argümanlar ve dönüşümler olabilir. Bu durumda, tam olarak neyin çağrıldığına her zaman emin olmak için en sınırlı kapsamı seçmeyi tercih ederim.

+0

Spekülasyon, ama bu benim de öbürüm. Çılgın uzaktaki aramalara ve yazım hatalarına güvenmek arasında ayrım yapmak zor. – Flexo

+0

"_It belirli bir zamanda ne kadar çok şeyin olduğunu unutmak kolay değil." Bu, burada saklanmaktan sakınmak için son derece güçlü bir argüman. – curiousguy

3

özel, çok şaşırtıcı, kural (ama sizin örnek için geçerli değildir) bir sınıf üye adı ad arama tarafından bulunduğunda, hiçbir ad kapsamları arandığını belirten yok:

#include <string> 

struct C { 
    std::string s; 

    explicit C (std::string); 

    void swap (C& rhs) { 
     swap (s, rhs.s); // error: swap is C::swap 
    } 
}; 

void swap (C& lhs, C& rhs) { 
    swap (lhs.s, rhs.s); // std::swap(string,string) 
} 

IMO, bu çılgınlık.

Ama serbest fonksiyonu böyle farklı imza sahip olduğu neden unambigious aramaları engeller:

İsim arama aşırı çözünürlük önce olur: arama belirsiz

  • , çözünürlüğü aşırı yapılmaz.
  • Geçerli bir işlev ad arama tarafından bulunamazsa, başka bir arama turu denenmez.

kural aşırı yükleme ve adı arama arasındaki "geri besleme" olmadan yeterince karmaşıktır. Karmaşıklıktan ziyade basitleştirme (üye gizler ad alanı kapsam kuralının kaldırılması ve belirsiz ad aramasının kaldırılması gibi) öneririm.

+0

Bu düşündüğünüz kadar çılgın değil. Bir eşleşme bulunduğunda isim araması durur (§3.4 civarında bir yerde belirtilir) ve içten dışa doğru bir düzen verilir. Yani bir isimde bir üye bulunursa, durur. Sürpriz değil. – Damon

+0

@Damon "Bir eşleşme bulunduğunda _Name araması durur" "ikinci" swap "aramamın gösterdiği gibi değil – curiousguy

İlgili konular