2009-12-05 16 views
8

साथ मैं एक टेम्पलेट आधारित वर्ग [Allotter.h & Allotter.cpp] काम कर रहा है:लिंकर त्रुटि 'अनसुलझे बाह्य प्रतीक': टेम्पलेट्स

template <typename allotType> class Allotter { 
public: 
Allotter(); 
quint32 getAllotment(allotType*); 
bool removeAllotment(quint32, int auto_destruct = 0); 

private: 
QVector<QPair<quint32, allotType*>> indexReg; 
int init_topIndex; 
}; 

और यह उपयोग के रूप में [ActiveListener.h & ActiveListener दिखाया गया है है। सीपीपी]:

class ActiveListener: public QObject { 
Q_OBJECT 

public: 
ActiveListener(); 

private slots: 
    void processConnections(); 
    void readFromSocket(int); 

private: 
QTcpServer* rootServer; 
QSignalMapper* signalGate; 
Allotter<QTcpSocket> TcpAllotter; 
}; 

मैं पूरी परिभाषा नहीं दिखा रहा हूं, क्योंकि इससे कोई फर्क नहीं पड़ता। समस्या तब होती है जब मैं संकलित करता हूं, सभी फाइलें ठीक से संकलित होती हैं। फाइलें वीसी ++ प्रोजेक्ट में हैं। इससे पहले जब मैंने Allotter के लिए टेम्पलेट-आधारित दृष्टिकोण का उपयोग नहीं किया था, तो सब कुछ संकलित और जुड़ा हुआ था।

1>ActiveListener.obj : error LNK2019: unresolved external symbol "public: __thiscall Allotter<class QTcpSocket>::Allotter<class QTcpSocket>(void)" ([email protected]@@@@[email protected]) referenced in function "public: __thiscall ActiveListener::ActiveListener(void)" ([email protected]@[email protected]) 
1>ActiveListener.obj : error LNK2019: unresolved external symbol "public: unsigned int __thiscall Allotter<class QTcpSocket>::getAllotment(class QTcpSocket *)" ([email protected][email protected]@@@@[email protected]@@Z) referenced in function "private: void __thiscall ActiveListener::processConnections(void)" ([email protected]@@AAEXXZ) 

आश्चर्य की बात बात है, कि निर्माता, ActiveListener::ActiveListener() सभी Allotter<QTcpSocket>::Allotter() पर किसी भी संदर्भ नहीं है: लेकिन अब, मैं इस त्रुटि मिलती है। हालांकि दूसरा संदर्भ मौजूद है। लेकिन मुझे समझ में नहीं आता कि लिंकर इस बाहरी प्रतीक को हल करने में सक्षम क्यों नहीं है।

निर्माण उत्पादन बस से पहले त्रुटियां प्रकट है:

1>Moc'ing ActiveListener.h... 
1>Compiling... 
1>stdafx.cpp 
1>Compiling... 
1>ActiveListener.cpp 
1>Allotter.cpp 
1>moc_ActiveListener.cpp 
1>main.cpp 
1>Generating Code... 
1>Linking... 

मैं अगर यह किसी भी प्रासंगिक है, क्योंकि यह सब पूरी तरह से पहले काम करता था समझ में नहीं आता है, ज्यादातर। यह सिर्फ इतना है कि टेम्पलेट्स का उपयोग करने के बाद एक समस्या होती है। किसी भी मदद की सराहना की जाएगी। बहुत बहुत धन्यवाद।

+0

आप सभी मदद की राशि आपके द्वारा दिए गए के लिए धन्यवाद। मैंने थोड़ा सा शोध किया और मुझे एक ही मुद्दे के लिए कुछ हद तक समाधान मिला: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.13 मैं इसे यहाँ डाल रहा हूं उन लोगों के लिए जो यहां ठोकरें हैं, इसी तरह की समस्याओं के समाधान की तलाश में हैं। फिर से धन्यवाद: डी –

+0

सरल टेम्पलेट वर्ग के साथ ["अपरिभाषित प्रतीकों" लिंकर त्रुटि का संभावित डुप्लिकेट] (http://stackoverflow.com/questions/999358/undefined-symbols-linker-error-with-simple-template-class) –

उत्तर

16

आप टेम्पलेट्स को .h और .cpp फ़ाइलों में विभाजित नहीं कर सकते हैं - आपको .h फ़ाइल में टेम्पलेट के लिए पूरा कोड डालना होगा।

+5

जब तक आप 'निर्यात' का उपयोग नहीं करते हैं, जो केवल परी कथाओं में काम करता है। –

+0

@ चार्ल्स: वास्तविक निर्यात में 'निर्यात' काम करता है (Comau संकलक के साथ)। –

+0

इसके लिए बहुत बहुत धन्यवाद: डी क्या आप मुझे यह बता सकते हैं कि ऐसा क्यों होता है? मुझे लगता है कि जब भी कंपाइलर को टेम्पलेट से एक विशिष्ट वर्ग की आवश्यकता होती है i.e. MyClass से MyClass , आवश्यक वर्ग उत्पन्न करने के लिए स्रोत कोड होना आवश्यक है। क्या मैं सही हूँ? –

1

चूंकि आप .cpp फ़ाइलों में टेम्पलेट कार्यान्वयन नहीं डाल सकते हैं, इसलिए इसे टेम्पलेट कार्यान्वयन के लिए .inl फ़ाइलों का उपयोग करने और टेम्पलेट शीर्षलेखों से शामिल करने के लिए एक अच्छा अभ्यास माना जाता है।

4

आम तौर पर इसे हेडर फाइलों के अंदर अपने टेम्पलेट कोड को लिखने के लिए सबसे अच्छा अभ्यास माना जाता है। इसके लिए एक महत्वपूर्ण तकनीकी कारण है: जब आप टेम्पलेट को तुरंत चालू करते हैं, तो C++ कंपाइलर को उस टेम्पलेट से कोड जेनरेट करने की आवश्यकता होती है जो आपके द्वारा निर्दिष्ट टेम्पलेट पैरामीटर के लिए विशिष्ट है। यदि आपका टेम्पलेट कोड पूरी तरह से आपके शीर्षकों में रखा गया है, तो यह आपके लिए स्वचालित रूप से किया जाता है।

यह सीपीपी फाइलों में कार्यान्वित कार्यान्वयन के साथ टेम्पलेट कोड लिखने के लिए निश्चित रूप से संभव है। यदि आप ऐसा करते हैं, तो आपको उस टेम्पलेट इंस्टेंस को स्पष्ट रूप से तत्काल करने की आवश्यकता है जिसका आप उपयोग करना चाहते हैं।

आपके मामले में, आप अपने प्रोजेक्ट में एक .cpp फ़ाइल में निम्न पंक्ति जोड़ने की जरूरत:

template class Allotter<QTcpSocket>; 
संबंधित मुद्दे