2010-01-20 24 views
8

Sınıf bildirimi içindeki bir şablon sınıfının üye işlevleri tanımlanması arasında bir fark var mıdır?Sınıfın içinde ve dışında tanımlanmış bir şablon sınıfı için üye işlevleri arasındaki fark

içinde tanımlanan:

template <typename T> 
class A 
{ 
public: 
    void method() 
    { 
     //... 
    } 
}; 

dışında tanımlanan:

şablon olmayan sınıfları için
template <typename T> 
class B 
{ 
public: 
    void method(); 
}; 

template <typename T> 
void B<T>::method() 
{ 
    //... 
} 

bu inlined olmayan satır içi yöntemler arasındaki farktır. Bu şablon sınıfları için de geçerli mi?

Meslektaşlarımın çoğu için varsayılan, sınıf içinde tanımları sağlamaktır, ancak her zaman sınıfın dışındaki tanımları tercih ettim. Tercihim haklı mı?

Düzenleme: Lütfen yukarıdaki kodun sınıf için başlık dosyasında sağlandığını varsayalım.

+0

Ben sınıf bildirimi içinde bir yöntem gövdesine tanımlayan yöntem satır içi yapar gösterir yerde bir başvuru görmedim. Bir şey mi kaçırdım? – Dathan

+0

@Dathan: Bak: http://www.parashift.com/c++-faq-lite/inline-functions.html#faq-9.8 Ve burada: http: //msdn.microsoft.com/en-us /library/bw1hbe6y%28VS.80%29.aspx – Ben

+3

@Dathan: hangi, "bir üye işlevi sınıf tanımında (8.4) tanımlanabilir: Sen diyor C++ standardının §9.3/2 kaçırdığınızı Bu bir satır içi üye işlevidir ... "Düzenleme: Ayrıca bu bir sınıf tanımı olduğunu unutmayın - bir sınıf beyanı gibi bir şeydir: sınıf x; –

cevap

2

Evet, aynısı, şablon sınıfları için de geçerlidir.

Şablon sınıfları için yöntem tanımlarının genellikle satır içi olarak tercih edilmesinin nedeni, şablonlarla, şablon tanımlandığında tüm tanımın görünür olması gerektiğidir.

Bazı ayrı .cpp dosyalarında işlev tanımını kullanırsanız, bir bağlayıcı hatası alırsınız. Tek genel çözüm, işlevi sınıf içinde veya dışarıda tanımlayarak inline anahtar sözcüğüyle satır içi yapmaktır. fakat her iki durumda da, işlevin çağrıldığı her yerde görünür olmalı, yani sınıf tanımıyla aynı başlıkta olması gerekir.

+0

Sadece meraktan çıkarılan şey, şu anda evrensel olarak doğru olan bağlayıcı hata mıdır? Derleyiciler farklı şablon örnekleme seçenekleri sağladılar. Örneğin, SGI Irix CC derleyicisi, bağlantı zamanı örneğine ayarlandı ve aslında şablon işlevi tanımlarını kendi .cpp dosyasında (örneğin, başlıkta değil, satır içi değil, görünürde göstermeye teşvik ediyor gibi görünüyordu) kodlama, diğer tüm satır içi işlev tanımları gibi) Sadece satır içi şablon işlevi tanımının, dil gereksinimine bir derleyici tercihi olarak değiştirilip değiştirilmediğini merak etme – Darryl

+0

@Darryl, extern şablonlarını tanımlarsınız. -standard uzatma, ve tüm derleyiciler desteklemez.Yeni standart, C++ 1x, 'extern' şablonları ekliyor Yani anahtar kelime gerektirir. – greyfade

+0

Şablonlar, bu özel ifadeyi kullanan her derleme biriminde derlenmiştir, ancak bunlar 'zayıf' sembolleridir (gcc terminolojisi, standardın ne olduğunu bilmiyorum) ve aynı sembolün birden fazla derleme biriminde tanımlanmış olması bağlantı hatası olmamalıdır. Yani, 'inline' şablon işlevlerine/yöntemlerine eklenmeye gerek yoktur. Bir başka ifade de, "inline" ın derleyiciye bir ipucu olmasıdır, ancak derleyici tarafından göz ardı edilebilir (ancak sembollerin nasıl oluşturulduğunu etkileyecek ve böylece bağlayıcı bir çift tanımdan şikayet etmeyecektir). –

1

Daha fazla yazmanın dışında bir fark yoktur. Bu, template bit, inline ve sınıfa atıfta bulunurken daha "ayrıntılı" adları kullanmak zorundadır. Örneğin

yöntem içine tanımlanır zaman A<T> bahsederken hep şablon parametre listesi <T> ihmal ve sadece A kullanabileceği
template <typename T> class A { 
    A method(A a) { 
    // whatever 
    } 
}; 

template <typename T> inline A<T> A<T>::method(A a) { 
    // whatever 
} 

Not için. Dışarıda tanımlarken, dönüş türünde ve yöntem adında "tam" adını kullanmanız gerekir (ancak parametre listesinde yer almaz).

+0

Her iki durumda da "yöntem" inline giriyorsunuz, bu da işlev gövdesi büyükse kötü olabilir. Bundan kaçınmaya çalışıyorum. – Ben

+2

** inline ** anahtar kelimesinin, aslında, işlevi en iyi duruma getirerek ve aynı işlevin birden fazla tanımına izin verilip verilmediğine bağlı olarak daha az şey vardır.Bir başlıkta bir işlev tanımlanmışsa (bu şablonlarla kaçınılmaz olan veya bir işlev bir sınıf bildiriminde tanımlandığında) ve birden çok derleme birimi bunu içerdiğinde, bağlayıcı son olarak çoklu (özdeş) tanımlarla sonlanır. aynı işlev/yöntem. ** inline ** anahtar sözcüğü (şablonlarla örtülü olması gereken), linker’ın tamam olduğunu söyler, aksi takdirde bir linker hatası olur. – UncleBens

+0

Konu, bir şablonla hiçbir seçeneğin olmadığı Ben'tir. Satır içi işaretli olmalı veya şablon çalışmayacak. Bu, bazı kişilerin şablonlardan hoşlanmadığı bir nedendir. Ayrıca, derleyicinin aslında arkanızdan ne istediğini yapabildiği şeyi yapmasını istemiyor. – Goz

0

Bunu biliyorum ... Sanırım tam olarak neye yardım edecek bir şey olmalı?

// This might be in a header file: 
template <typename T> 
class xyz { 
    void foo(); 
    }; 

// ...

// This might be later on in the header file: 
    void xyz<T>::foo() { 
// generic definition of foo() 
    } 

Bu için yanlıştır:

defining a member function outside of its template 

Böyle bir şablon sınıfın üyesi fonksiyonunun tanımını sağlamak için Tamam değil birkaç sebep. Yani şu:

 void xyz<class T>::foo() { 
     // generic definition of foo() 
     } 

doğru tanımı şablonu anahtar kelime ve sınıf şablonun tanımı ile ilan edildi aynı şablon argümanları ihtiyacı var.vb üyesi şablonun yanı şablon direktifleri diğer türleri, olduğu

 template <typename T> 
      void xyz<T>::foo() { 
      // generic definition of foo() 
       } 

Not ve her biri kendi formda alır: Yani verir. Önemli olan, sahip olduğunuz herşeyi nasıl yazacağınızı bilmektir. Bu özellikle, bazı derleyicilerin hata mesajlarının neyin yanlış olduğu konusunda net olmayabilir. Ve tabii ki, iyi ve güncel bir kitap olsun.

bir şablon içinde yuvalanmış bir üye şablonu varsa:

template <typename T> 
     struct xyz { 
     // ... 
     template <typename U> 
     struct abc; 
     // ... 
     }; 

nasıl xyz dışında abc tanımlarım

?

 template <typename U> 
    struct xyz::abc<U> { // Nope 
     // ... 
    }; 

ne de yapar: Bu işe yaramazsa

template <typename T, typename U> 
struct xyz<T>::abc<U> { // Nope 
// ... 
}; 

Bunu yapmak zorunda kalacak: abc bir "birincil" olduğu için ...abc değil ...abc<U> olduğunu

 template <typename T> 
     template <typename U> 
      struct xyz<T>::abc { 
      // ... 
      }; 

Not şablonu. IOWs, bu iyi değil:

// burada izin verilmiyor: template template struct xyz :: abc {};

İlgili konular