2013-06-19 16 views
7

Ziyaretçi modelini gösteren birkaç örnek gördüm. Hepsinde, türetilen ziyaret edilen öğeler genellikle Accept() yöntemi olarak adlandırılan şeyi uygular.C++ ziyaretçi kalıbı: Neden her bir türevi ziyaret edildi Accept()?

renklerin bir hiyerarşi içinde

, bu yöntem gibi görünebilir:

void Red::accept(Visitor *v) 
{ 
    v->visit(*this); 
} 

void Blue::accept(Visitor *v) 
{ 
    v->visit(*this); 
} 

Ziyaretçi yanı sıra varisleri, yöntemler varsa: Bu uygulamıyor neden

visit(Red red); 
visit(Blue blue) 

Benim sorum sadece (bu örnekte: Color) temel sınıfta aynı şekilde iş yapacak ve polimorfizm, yani doğru ziyareti nesne bu var dinamik tip böylece dereferencing bir Red bir Red ne zamandan beri adı verilecek Red'u verecek ve bu da ziyaretin (kırmızı) çağrılmasına neden olacak mı?

Neyi eksik? Sahip olduğun, tek accept olsaydı ...

+4

Eğer bir temel sınıfta isterseniz, o zaman [İlginççe yinelenen şablon şablonunu] kullanmak zorundasınız (https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). – user1810087

+0

Daha dinamik bir dilde, 'visitBlue' ve' visitRed' işlevlerini adlandırmanız gerekebilir. Bunu da burada yapabilirsin. Bu işe yarar mı? –

+1

Yanıt zaten sağlandı, ancak web'de "çift gönderim" için arama yapan daha fazla bilgi bulabilirsiniz (zaten "ziyaretçi modelini aramış olduğunuzu varsayalım ve size yardımcı olmadı"), kullanılan tekniğin adı budur İşte. –

cevap

8

Kalıtım polimorfizmi (dinamik sevk) argümanları çalışması için geçerli değildir. Diğer bir deyişle, aşılmış olan argümanların statik tipinde aşırı yüklenmiş fonksiyon seçilir. Color taban sınıfında uygulandığında, v->visit(*this) her zaman visit(Color c)'u arar.

+0

Net ve doğru noktaya. Kafam karışmamı sağlayan şey, temelde sanal olmayan bir işleve sahip olduğumda ve sanal bir işlevi kendi içimden çağırdığımda, polimorfizm çalışacak ve eğer var ise sanal olarak çağrılacak. – Subway

+1

Ben – Massa

+1

@Massa, inanıyorum ... (başvuruyla geçirirseniz ** ve ** Doğru sanal işlevlere sahip çünkü, o zaman geçerli olacaktır) o "değer geçirilecek argümanları işlev için geçerli değildir" için düzenlersiniz yaniliyosun. Referans ya da değil, hangi aşırı yüklenmiş fonksiyonun çağrılacağını seçmek için kullanılan argümanların statik türleridir. C++ 'da çift gönderim yoktur, sadece bu ziyaretçi modeli tarafından simüle edilir. http://en.wikipedia.org/wiki/Double_dispatch – rectummelancolique

1

void Color::accept(Visitor* v) 
{ 
    v->visit(*this); 
} 

visit sadece temel sınıf ile denilen olsun istiyorum. Doğru türetilmiş sınıf ile visit çağırabilmek için onlar bir doğru this Yazılan geçebilir böylece bunu uygulamak için her Color gerek, bu yüzden doğru visit aşırı yük denir.

1

Anlayışım, temel sınıf yöntemlerinde this işaretçisinin türetilmiş türden değil, türetilmiş sınıflardan oluşmasıdır, dolayısıyla yalnızca temel sınıf yöntemlerine erişebilir ve Color* this türüne geçirilir. Ziyaret yöntemine geçildiğinde, visit(Color* color)'u çalıştırarak polimorfik davranışlar yalnızca sınıfın kendi yöntemlerine (diğer sınıflara değil) uygulanır.

+0

Ne, ne, ne? –

+0

Tabanda sanal olmayan bir işleve sahip olduğumda ve sanal bir işlevi kendi içimden aradığımda, polimorfizm çalışacak ve eğer var ise, sanal sunucunun ismi çağrılacak mı? – Subway

+0

Evet, ancak bu durumda bu dinamik dağıtımı işleyen vtable'a erişimi var. Ziyaretçi deseninde kullanılan ilgisiz sınıflar arasında geçerli olmayan özel bir durumdur. – Utopia

İlgili konular