2011-02-07 18 views
6

Olası Çoğalt: operator->() zincirli olması
Overloading operator ->Operatör-> İşaretçiler için "zincirleme"?

Merhaba,

Ben mesela o değerlendirilir sonra, (uygulanan yeniden) gördüm:

struct Bar 
{ 
    Bar() : m_str("Hello world!") {} 
    const string* operator->() const { return &m_str; } 
    string m_str; 
}; 

struct Foo 
{ 
    const Bar& operator->() const { return m_bar; } 
    Bar m_bar; 
}; 

int main() 
{ 
    Foo f; 
    cout << f->c_str() << endl; 
    return 0; 
} 

oldukça iyi çalışıyor, gerektiren Değerlendirilmek üzere üç operator->() - Foo::operator->(), Bar::operator->() ve düzenli işaretçi çözünürlüğü.

Ancak ortadaki işaretçilerle çalışmaz - Foo::operator->() işaretçiyi Bar yerine döndürürse, derleme yapmaz. Aynı şey, örneğin auto_ptr<auto_ptr<string>> ile olur.

Bu, aşırı yüklenmemiş operator->()'a özgüdür, bu nedenle yalnızca bir kez uygulanır ve zincirlemeye neden olmaz? (*ptr2)-> ... kullanmadan kodun altında çalışma yapmak mümkün mü?

int main() 
{ 
    string s = "Hello world"; 
    auto_ptr<string> ptr1(&s); 
    auto_ptr<auto_ptr<string> > ptr2(&ptr1); 
    cout << ptr1->c_str() << endl; // fine 
    cout << ptr2->c_str() << endl; // breaks compilation 
} 

Teşekkürler!

+0

[Aşırı yükleme işleci ->] (http://stackoverflow.com/questions/4896238/overloading-operator) [AndreyT'nin yanıtı, operatörün davranışını ve zincirlemenin nasıl oluştuğunu açıklar.] –

+1

@James Sorunun ifadesi farklı olduğu için bunu açık tutmayı tercih ederim. Diğer insanların bu cevabı bulmasına yardımcı olabilir. –

+2

@Judge: Kapalı bir soru otomatik olarak silinmez ve bunun gibi iyi sorulan bir soru silinmez; soru hala var olacak ve aranabilir. –

cevap

12

C++ 98 standart §13.5.6/1 "sınıf üyesi":

bir ifade x->m tip T::operator-> varsa T bir sınıf nesnesi x ve operatör eğer (x.operator->())->m yorumlanır aşırı yük çözme mekanizması (13.3) ile en iyi eşleşme işlevinde seçildi. Bunun pratikteki anlamı nedir

x bir işaretçi olduğu zaman, sen t ’ yok zincirleme olsun olmasıdır; Daha sonra sadece operator-> (x işaretçisiyle (*x).m işaretçisini) elde edin.

x, T sınıf türünün bir nesnesi olduğunda, zincirleme efektini alabilirsiniz.Çünkü o zaman (x.operator->())->m olarak yorumlama, (x.operator->())'un kendisi, sınıfın bir nesnesi U dersi olabilir. Bu nedenle, ikinci ->, U::operator-> olarak çözülebilir ve böyle devam ederse, sonuç bir sınıf tipi nesne ve hellip;

gibi durumda da, Foo::operator-> bir operator-> tanımlamaz (referans için) sınıfı Bar bir nesne oluşturur.

Ancak operator-> bir işaretçi döndürdüğünde olarak ör std::auto_ptr<T>::operator-> yapar, o zaman kullanılan sadece yerleşik operator-> var. Geçerken

, zincirleme pratikte uygunsuz delete kullanılmasını engellemelisiniz için kullanılabilir. std::auto_ptr bunu yapmaz. Ve ben ’ ve bunu hiç görmedim. Bir akıllı işaretçi tarafından yönetilen işlenmemiş işaretin yanlışlıkla delete nasıl engelleneceği hakkında [comp.lang.C++. Moderated] 'da uzun bir tartışma başlığı vardı ve bu tartışılan bir olasılıktı.

Şerefe & hth.

0

Hayır, çalışması mümkün değil. string * için operator ->'u aşırı yüklerseniz, çalışmasını sağlayabilirsiniz. Ancak operator -> zaten tüm işaretçi türleri için bir tanıma sahiptir. Yani, ilkel sayısal türler için +'u aşırı yükleyemediğiniz gibi, herhangi bir işaretçi türü için operator ->'u aşırı yükleyemezsiniz.

Ve yapsanız bile, derleyici özyinenin ne zaman sona ermesi gerektiğini nasıl bilebilir?

3

İlk örneğinizin çalışmasının nedeni, bir işaretçi yerine bir başvuru döndürmenizdir. Bu operatör aşırı yüklenme durumu dışında normalde geçersiz olur. Bu nedenle, derleyici aşırı yüklenmiş işlevleri zincirden yürütmelidir. Ancak, auto_ptr durumunda, gerçek bir işaretçi döndürülür ve varsayılan işaretçiler için varsayılan operator -> çağrılır.

Daha fazla bilgi için lütfen Overloading operator -> sorusuna bakın.

+0

Cevabınız için teşekkür ederiz. > vektörünü tekrarlamak ve benzer şeyler için kodu basitleştirmek için bir yaklaşım arıyordum. Tek seçeneğin, vector_ (herhangi bir kapsayıcı) yineleyicisini, kabul edilemez olan shared_ptr (diğer bazı akıllı ptr'ler) için uzmanlaştırmak olduğu görünüyor. – nyrl