2008-11-04 13 views
79

Sanal üye işlevlerinin ek yükünü önlemek için CRTP'yi C++'da nasıl kullanabilirim?Dinamik polimorfizmden kaçınmak için CRTP

+5

Merhaba, tüm cevaplarınız için teşekkürler. CRTP'nin mekaniğini anlıyorum. Bununla birlikte, problem gerçekten polimorfizm olmamasıdır, yani X: base {} ve Y: base {} ise X & Y ilişkisiz türleridir. yani onları aynı kapta tutamam ya da türetilmiş türden haberi olmadan kullanamıyorum. –

+11

Bu _is_ polimorfizmi, beit statik - CRTP'ye giderken, aynı zamanda (statik olarak) polimorf olan templatized istemci kodu da oluşturacaksınız: başka bir türle çalışması için bir kod baytını değiştirmeniz gerekmez. – xtofl

cevap

1

CRTP'a bakmak zorundaydım. Ancak bunu yaptıktan sonra, Static Polymorphism hakkında bir şeyler buldum. Bu sorunun cevabı olduğundan şüpheleniyorum.

ATL'un bu modeli oldukça kapsamlı bir şekilde kullandığı ortaya çıkıyor.

-3

This Vikipedi cevabı ihtiyacınız olan her şeye sahiptir. Yani: Bu aslında ne kadar satın aldığımı bilmeme rağmen.

  • Bellek:: Sanal fonksiyonu
  • Süre başına bir fonksiyon işaretçisi: Tek işlev işaretçisi çağrı

cRTP yükü iken sanal bir işlev çağrısı havai (tabii bağımlı derleyici,) 'dir statik polimorfizmidir:

  • Bellek: bir fonk: Çoğaltma Base şablon örnekleme
  • Süre başına tion pointer call + her ne yapıyor static_cast
  • yapıyor
+4

Aslında, şablon başına temelin çoğaltılması bir yanılsamadır, çünkü (hala bir vtable'ınız yoksa) derleyici tabanın depolanmasını birleştirir ve sizin için tek bir yapıya türetilir.İşlev işaretçisi çağrısı, derleyici (static_cast bölümü) tarafından da optimize edilmiştir. –

+16

Bu arada, CRTP analiziniz yanlış. Olması gereken: Bellek: Dean Michael'ın dediği gibi hiçbir şey yok. Çalışma Zamanı: Alıştırmanın tüm noktası olan sanal değil, bir (daha hızlı) statik işlev çağrısı. static_cast hiçbir şey yapmaz, sadece kodun derlenmesine izin verir. –

+2

Benim esas nokta, tüm şablon örneklerinde temel kodun çoğaltılacağıdır (konuştuğunuz çok birleştirici). Şablon parametresine dayanan sadece bir yöntemle bir şablona sahip olmak; Diğer her şey bir temel sınıfta daha iyidir, aksi takdirde birden çok kez ('birleştirilir') çekilir. – user23167

19

Kendimi iyi CRTP tartışmalar için arıyorum. Todd Veldhuizen Techniques for Scientific C++, bunun için harika bir kaynaktır (1.3) ve ifade şablonları gibi diğer birçok gelişmiş tekniktir.

Ayrıca, Coplien'in orijinal C++ Gems makalesinin çoğunu Google kitaplarında okuyabileceğinizi öğrendim. Belki de durum böyle.

+0

@fizzer Size önerdiğiniz parçayı okudum, ancak yine de çift toplamı şablonunu (Matrix & A);, şablon double sum'a göre satın aldığınızı anlamıyorsunuz (Ne olursa olsun & A); –

+0

@AntonDaneyko Bir temel örnekte, temel sınıfın toplamı, örneğin "bir alanın alanı" olarak adlandırılır, örneğin bir kare gibi varsayılan uygulama ile. Bu durumda CRTP'nin hedefi, en türetilmiş uygulamayı çözmektir. " Bir trapezoid "vb. türetilmiş davranış gerekli olana kadar şekil olarak trapezoid'e başvurabilirken. Normalde" dynamic_cast "veya sanal yöntemlere ihtiyacınız olduğunda. –

120

İki yol vardır.

ilk türleri yapısına statik bir arayüz belirterek olup:

template <class Derived> 
struct base { 
    void foo() { 
    static_cast<Derived *>(this)->foo(); 
    }; 
}; 

struct my_type : base<my_type> { 
    void foo(); // required to compile. 
}; 

struct your_type : base<your_type> { 
    void foo(); // required to compile. 
}; 

ikinci referans ile taban veya işaretçi ile taban deyim ve kullanımından kaçınmak sürmektir derleme zamanında kablolama.

template <class T> // T is deduced at compile-time 
void bar(base<T> & obj) { 
    obj.foo(); // will do static dispatch 
} 

struct not_derived_from_base { }; // notice, not derived from base 

// ... 
my_type my_instance; 
your_type your_instance; 
not_derived_from_base invalid_instance; 
bar(my_instance); // will call my_instance.foo() 
bar(your_instance); // will call your_instance.foo() 
bar(invalid_instance); // compile error, cannot deduce correct overload 

Yani yapı/arayüz tanımı ve işlevleri derleme zamanı tür kesinti birleştirerek yerine dinamik sevk statik sevkini yapmak için izin verir: Yukarıdaki tanım kullanarak, bu gibi bakmak şablon işlevleri olabilir. Bu statik polimorfizmin özüdür.

+1

iyi örnek, teşekkürler – ttvd

+14

Mükemmel cevap –

+0

Teşekkürler – Yola

İlgili konular