2009-03-16 14 views
50

का अमान्य उपयोग मैं अपने प्रोजेक्ट में उप-वर्ग से टाइपिफ़ का उपयोग करने की कोशिश कर रहा हूं, मैंने नीचे दिए गए उदाहरण में अपनी समस्या को अलग कर दिया है।अपूर्ण प्रकार

क्या कोई जानता है कि मैं कहां गलत हो रहा हूं?

[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’ 

उत्तर

57

कारण यह है कि जब एक वर्ग टेम्पलेट instantiating, सभी अपनी घोषणाओं (नहीं परिभाषाएं) इसके सदस्य कार्यों के भी तत्काल हैं। कक्षा टेम्पलेट को तुरंत ठीक किया जाता है जब विशेषज्ञता की पूर्ण परिभाषा की आवश्यकता होती है। यही वह मामला है जब इसे बेस क्लास के रूप में उपयोग किया जाता है, उदाहरण के लिए, जैसा कि आपके मामले में है।

तो क्या होता है और इस बिंदु पर B नहीं एक पूर्ण प्रकार है अभी तक (यह वर्ग परिभाषा के समापन ब्रेस के बाद है) कि A<B>

class B : public A<B> 

पर instantiated जाता है। हालांकि, A<B>::action की घोषणा, B की आवश्यकता है पूरा हो सकता है क्योंकि यह यह के दायरे में क्रॉल कर रहा है:

Subclass::mytype 

आप क्या करना कुछ बिंदु B पूरा हो गया है, जिस पर करने के लिए इन्स्टेन्शियशन में देरी कर रहा है की जरूरत है। ऐसा करने का एक तरीका यह है कि इसे सदस्य टेम्पलेट बनाने के लिए action की घोषणा को संशोधित करना है।

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

यह अभी भी टाइप-सुरक्षित है, क्योंकि var, सही प्रकार का नहीं है vardo_action को गुजर विफल हो जाएगा।

+1

मैं अपने कोड के थोड़े पुनर्गठन के लिए बस गया (कुछ अन्य संबंधित मुद्दों के कारण मैंने यहां वर्णन नहीं किया) लेकिन मैंने इस दृष्टिकोण का परीक्षण किया और यह वास्तव में समस्या को ठीक करता है। धन्यवाद! – seanhodges

0

आप एक सूचक या उचित प्रकार इस समय संकलक यह दृष्टांत नहीं कर सकते पर नहीं जाना जाता है के रूप में एक संदर्भ का उपयोग करने की जरूरत है:

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; 
} 

यह आउटपुट मैं हो रही है।

इसके बजाय का प्रयास करें:

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

मैंने इसे संदर्भ में बदलने की कोशिश की और फिर एक सूचक, और त्रुटि अभी भी वही है। हालांकि मैं आपकी बात समझता हूं। – seanhodges

2

आप A<B> से B निकाले जाते हैं, इसलिए पहली बात संकलक करता है, एक बार यह वर्ग B की परिभाषा देखता A<B> का दृष्टांत करने की कोशिश करने के लिए है। ऐसा करने के लिए action के पैरामीटर के लिए इसे B::mytype ज्ञात करने की आवश्यकता है। लेकिन चूंकि संकलक B की वास्तविक परिभाषा को समझने की प्रक्रिया में है, इसलिए यह अभी तक इस प्रकार को नहीं जानता है और आपको एक त्रुटि मिलती है। इस के आसपास

एक तरह से, एक और टेम्पलेट पैरामीटर के रूप में पैरामीटर प्रकार की घोषणा करने के होगा बजाय व्युत्पन्न वर्ग के अंदर की:

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

क्या नहीं वास्तव में आप पूछ रहे थे, लेकिन आप कार्रवाई एक टेम्पलेट सदस्य समारोह बना सकते हैं:

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

आप एक लक्षण वर्ग का उपयोग करके यह आसपास पहुंच सकते हैं:
यह जरूरी है कि आप एक specialsed लक्षण वर्ग की स्थापना आपके द्वारा उपयोग की जाने वाली प्रत्येक एक्ट्यूअल क्लास के लिए।

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; 
} 
संबंधित मुद्दे