2012-01-12 13 views
14

संभव डुप्लिकेट:
Why can templates only be implemented in the header file?.cpp फ़ाइल शामिल करें?

मैं चारों ओर की कोशिश कर रहा है के साथ हाल ही में सी ++। फिलहाल मैं कुछ प्रोग्राम करने की कोशिश कर रहा हूं, मुझे यकीन है कि कभी भी कम से कम एक बार किया गया है: एक साधारण लिंक्डलिस्ट क्लास। कोड किया गया है, लेकिन मैं इसे संकलित करने में असफल रहा हूं। मैं googling गया है और ऐसा लगता है जैसे मैं ऑब्जेक्ट फ़ाइलों को गलत जोड़ रहा हूँ। यही कारण है कि मेरी कोड मूल रूप से दिखाई देता है जैसे:

test.cpp

#include "linkedlist.h" 

int main() 
{ 
    LinkedList<int> list; 
    // do something 
} 

linkedlist.h

template <typename T> 
class LinkedList 
{ 
    // a lot of function and variable definitions 
} 

तो फिर वहाँ जो सभी के वास्तविक कोड में शामिल है एक .cpp फ़ाइल linkedlist.cpp कहा जाता है लिंकरलिस्ट वर्ग। जब निम्न आदेश का उपयोग कर test.cpp संकलित करने के लिए कोशिश कर रहा है:

g++ ..\src\test.cpp 

मुझे बताया गया हो रही वहाँ 'LinkedList :: LinkedList()' के लिए एक अपरिभाषित संदर्भ है कि। तो मैं सोच किया गया है कि यह गलत जोड़ा जा रहा है के रूप में वहाँ एक से अधिक .cpp फ़ाइल है, तो मैं इसे इस तरह की कोशिश की:

g++ -c -Wall -O2 ..\src\test.cpp 
g++ -c -Wall -O2 ..\src\linkedlist.cpp 
g++ -s test.o linkedlist.o 

बहरहाल, यह कुछ भी नहीं बदलता है। त्रुटि संदेश वही रहते हैं। मैं इंटरनेट पर कुछ जानकारी खोजने की कोशिश कर रहा हूं, हालांकि, यह वास्तव में काम नहीं करता था।

+3

यह पूरी तरह से और सुसंगत रूप से तैयार करने के लिए किया गया है। :) एक नवागंतुक के लिए दुर्लभ, आजकल :( –

+0

चूंकि 'लिंक्डलिस्ट' एक टेम्पलेट वर्ग है, इसलिए उस वर्ग के उपयोगकर्ताओं को सभी विधियों की पूर्ण परिभाषा की आवश्यकता होती है। ऐसा करने का एक तरीका कक्षा में सभी विधियों को इनलाइन करना है, जबकि दूसरा विधियों को एक अलग फ़ाइल में रखने के लिए और उन्हें हेडर फ़ाइल में शामिल करें। –

+0

@ माइक: इसे "डुप्लिकेट" प्रति से कॉल करना मुश्किल है। यह वह जगह है जहां चीजें अस्पष्ट होती हैं - सवाल पूरी तरह से अलग है, भले ही हम डॉन न करें एक ही जमीन को फिर से कवर करने की आवश्यकता नहीं है। :) –

उत्तर

5

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

कारण यह है कि टेम्पलेट्स काम करते हैं। संकलन के दौरान, कंपाइलर आपकी कक्षा टेम्पलेट परिभाषा के आधार पर टेम्पलेट कक्षाओं को तुरंत चालू करता है। इसके लिए केवल घोषणाओं या हस्ताक्षर तक पहुंच नहीं है: इसे पूरी परिभाषा उपलब्ध कराने की आवश्यकता है।

.cpp फ़ाइल और .h फ़ाइल में से अपनी सभी विधि परिभाषाओं को ले जाएं, और सबकुछ ठीक होना चाहिए (मान लीजिए कि आपने वास्तव में डिफ़ॉल्ट निर्माता के लिए परिभाषा प्रदान की है!)।

वैकल्पिक रूप से, आप template class LinkedList<int> जैसे कुछ का उपयोग कर उचित टेम्पलेट वर्ग को तुरंत चालू करने के लिए अपने कंपाइलर को स्पष्ट रूप से बताकर इसे प्राप्त करने में सक्षम हो सकते हैं, लेकिन यह वास्तव में इस तरह के एक साधारण मामले में आवश्यक नहीं है। हेडर फ़ाइल में सभी परिभाषाओं सहित इस का प्राथमिक लाभ यह है कि यह संभावित रूप से कोड ब्लोट को कम करता है और संकलन को गति देता है। लेकिन यह आवश्यक नहीं हो सकता है, क्योंकि कंप्यूटर्स को उचित अनुकूलन लागू करने में बहुत अधिक स्मार्ट प्राप्त हुआ है।

+2

'निर्यात' कीवर्ड अब मौजूद नहीं है, और यह केवल पहले ही अस्पष्ट रूप से समर्थित था। –

2

आपने अपनी कक्षा LinkedList विभाजित कर दी है और एक स्रोत-फ़ाइल में एक शीर्षलेख और परिभाषा में घोषणा की है। This does not work for a template। दोनों को हेडर में होना है।

+0

उन्होंने वास्तव में कहा था 'फिर एक .cpp फ़ाइल है जिसे linkedlist.cpp कहा जाता है जिसमें लिंकरलिस्ट क्लास के सभी वास्तविक कोड शामिल हैं। –

+0

जो मुझे केवल स्किमिंग प्रश्नों के लिए मिलता है - इसे ठीक करता है। –

+0

आपको इस तरह के प्रश्नों के लिए क्षमा किया गया है;) –

1

LinkedList एक वर्ग टेम्पलेट, the definitions of its member functions ought to go in a header है।

(वे नहीं है , होना करने के लिए है कडाई के साथ है, लेकिन इस सबसे आसान तरीका पूरी तरह से बंद piste शामिल किए जाने के सम्मेलनों के साथ जा रहा बिना टेम्पलेट इन्स्टेन्शियशन की जटिलताओं से बचने के लिए है।)

ओह, और आपको अपना दूसरा वैसे भी दृष्टिकोण बनाना होगा; आपको सभी .cpp फ़ाइलों को एकसाथ लिंक करना चाहिए, या -c एक समय में संकलित करने के लिए स्विच करें, फिर बाद में परिणामों को लिंक करें।

0

वहाँ 'LinkedList :: LinkedList()' के लिए एक अपरिभाषित संदर्भ

आप अपने LinkedList वर्ग एक निर्माता है, तो देखने के लिए जांच की है है?

1

टेम्पलेट क्लास एक नियम की परिभाषा की तरह है जिसके द्वारा एक वास्तविक वर्ग का निर्माण किया जाता है। जहां भी टेम्पलेट वर्ग की तत्कालता है वहां वास्तविक कक्षाएं संकलित द्वारा बनाई जाती हैं (तत्काल)। इस कारण से टेम्पलेट क्लास का सभी कोड उस बिंदु पर एक कंपाइलर के लिए दृश्यमान होना चाहिए, और यही कारण है कि आपको हेडर फ़ाइलों में सभी टेम्पलेट फ़ंक्शंस और विधियां लिखनी होंगी - क्योंकि आप केवल सीपीपी फाइलों में हेडर शामिल करते हैं, केवल हेडर दिखाई दे रहे हैं उस बिंदु पर एक कंपाइलर के लिए। आप सीपीपी फ़ाइलों को किसी अन्य सीपीपी फाइलों में शामिल नहीं करते हैं, और आपको ऐसा कभी नहीं करना चाहिए।

मेरी समझ गलत है अगर मुझे सही करें।

पी एस क्या सी ++ 11 इस मुद्दे को संबोधित करता है?

+1

पीएस नहीं, नहीं, यह नहीं है। सी ++ 03 ने कोशिश की और असफल रहा, इसलिए सी ++ 11 ने छोड़ दिया और वास्तव में प्रयास को हटा दिया। –

संबंधित मुद्दे