2009-03-16 16 views
50

Projemde bir alt sınıftan typedef kullanmaya çalışıyorum, aşağıdaki örnekte sorunumu çözdüm.tamamlanmamış türün geçersiz kullanımı

Nerede yanlış gittiğimi bilen var mı?

[email protected]:~/Documents/LucadeStudios/experiments$ g++ -o test test.cpp 
test.cpp: In instantiation of ‘A<B>’: 
test.cpp:10: instantiated from here 
test.cpp:5: error: invalid use of incomplete type ‘class B’ 
test.cpp:10: error: forward declaration of ‘class B’ 

cevap

57

nedeni olduğuna dair bir sınıf örnekleniminden, tüm beyanlar (değil üye fonksiyonlarının tanımları da başlatılmıştır. Sınıf şablonu, tam bir uzmanlık tanımının gerekli olduğu durumlarda tam olarak oluşturulur. Örneğin sizin durumunuzda olduğu gibi bir temel sınıf olarak kullanıldığında bu durum geçerlidir.

ne olur bu noktada B henüz tam bir türüdür (Bu sınıf tanımının Kapanış ayracı sonradır) A<B>

class B : public A<B> 

de örneği olmasıdır. o kapsamında taradığını Ancak, A<B>::action beyanı, tam olduğu B gerektirir:

Subclass::mytype 

Ne B tamamlandığında hangi bir noktaya örnekleme geciktirdiğini yapmak gerekir. Bunu yapmanın bir yolu, bir üye şablonu yapmak için action bildirimini değiştirmektir.

template<typename T> 
void action(T var) { 
    (static_cast<Subclass*>(this))->do_action(var); 
} 

Hala tip-güvenli olduğu var başarısız olur vardo_action geçerek, sağ türde değil çünkü eğer.

+1

Kodumu yeniden yapılandırmaya karar verdim (burada açıklamamış diğer bazı sorunlar nedeniyle), ancak bu yaklaşımı test ettim ve gerçekten sorunu çözdüm. Teşekkürler! – seanhodges

0

Bir işaretçi veya derleyici örnekleriz olamaz şu anda bilinmemektedir uygun türü olarak bir başvuru kullanmanız gerekir:

template<typename Subclass> 
class A { 
    public: 
     //Why doesn't it like this? 
     void action(typename Subclass::mytype var) { 
      (static_cast<Subclass*>(this))->do_action(var); 
     } 
}; 

class B : public A<B> { 
    public: 
     typedef int mytype; 

     B() {} 

     void do_action(mytype var) { 
      // Do stuff 
     } 
}; 

int main(int argc, char** argv) { 
    B myInstance; 
    return 0; 
} 

Bu

çıktı alıyorum olduğunu.

void action(const typename Subclass::mytype &var) { 
      (static_cast<Subclass*>(this))->do_action(); 
    } 
+0

Bir referansa ve ardından bir işaretçiye değiştirmeyi denedim ve hata hala aynı. Senin amacını anlıyorum. – seanhodges

2

Sen A<B> dan B türetmek, bu nedenle sınıfın B tanımını gördüğünde derleyici, yaptığı ilk şey A<B> örneğini çalışmaktır:

yerine deneyin. Bunu yapmak için action parametresi için B::mytype bilinmelidir. Ancak derleyici sadece B'un gerçek tanımını bulma sürecinde olduğundan, bu türden bir şey bilmiyor ve bir hata alıyorsunuz. Bu çevrede

bir yolu yerine türetilmiş sınıf içinde bir başka şablon parametresi olarak parametre türü ilan etmek olurdu geçerli:

template<typename Subclass, typename Param> 
class A { 
    public: 
     void action(Param var) { 
       (static_cast<Subclass*>(this))->do_action(var); 
     } 
}; 

class B : public A<B, int> { ... }; 
1

Tam olarak ne soran, ancak eyleme bir şablon üye işlev yapabilir: Bir specialsed özellikleri sınıfını ayarlamak
O gerektirir:

template<typename Subclass> 
class A { 
    public: 
     //Why doesn't it like this? 
     template<class V> void action(V var) { 
       (static_cast<Subclass*>(this))->do_action(); 
     } 
}; 

class B : public A<B> { 
    public: 
     typedef int mytype; 

     B() {} 

     void do_action(mytype var) { 
       // Do stuff 
     } 
}; 

int main(int argc, char** argv) { 
    B myInstance; 
    return 0; 
} 
22

Bir özellikleri sınıfını kullanarak bu sorunun üstesinden gelebilirsiniz Kullandığınız her actuall sınıfı için.

template<typename SubClass> 
class SubClass_traits 
{}; 

template<typename Subclass> 
class A { 
    public: 
     void action(typename SubClass_traits<Subclass>::mytype var) 
     { 
       (static_cast<Subclass*>(this))->do_action(var); 
     } 
}; 


// Definitions for B 
class B; // Forward declare 

template<> // Define traits for B. So other classes can use it. 
class SubClass_traits<B> 
{ 
    public: 
     typedef int mytype; 
}; 

// Define B 
class B : public A<B> 
{ 
    // Define mytype in terms of the traits type. 
    typedef SubClass_traits<B>::mytype mytype; 
    public: 

     B() {} 

     void do_action(mytype var) { 
       // Do stuff 
     } 
}; 

int main(int argc, char** argv) 
{ 
    B myInstance; 
    return 0; 
}