C ++ STL टेम्प्लेट पर इतना भारी क्यों है? (और * इंटरफेस * पर नहीं)


211

मेरा मतलब है, अपने अलग नाम (मानक टेम्पलेट लाइब्रेरी) से अलग ...

C ++ ने शुरू में OOP अवधारणाओं को C. में प्रस्तुत करने का इरादा किया था। यह है: आप बता सकते हैं कि एक विशिष्ट इकाई क्या कर सकती है और क्या कर सकती है (इसकी परवाह किए बिना कि वह कैसे करता है) अपने वर्ग और वर्ग पदानुक्रम के आधार पर। क्षमताओं की कुछ रचनाएँ कई तरह की विरासत की समस्याओं के कारण इस तरीके से वर्णन करना अधिक कठिन है, और तथ्य यह है कि सी ++ कुछ हद तक अनाड़ी तरीके से इंटरफेस की अवधारणा का समर्थन करता है (जावा, आदि की तुलना में), लेकिन यह वहां है (और हो सकता है) सुधार)।

और फिर टेम्पलेट एसटीएल के साथ-साथ चलन में आए। एसटीएल ने शास्त्रीय ओओपी अवधारणाओं को लिया और इसके बजाय टेम्पलेट्स का उपयोग करते हुए उन्हें नाली में बहा दिया।

ऐसे मामलों में अंतर होना चाहिए जब टेम्प्लेट का उपयोग उन प्रकारों को सामान्य बनाने के लिए किया जाता है, जहां टेम्प्लेट के संचालन के लिए प्रकार के विषयवस्तु अप्रासंगिक हैं (उदाहरण के लिए कंटेनर)। एक vector<int>सही समझ में आता है।

हालाँकि, कई अन्य मामलों में (पुनरावृत्तियों और एल्गोरिदम), टेम्पर्ड प्रकारों को एक "अवधारणा" (इनपुट Iterator, फॉरवर्ड Iterator, आदि ...) का पालन करना चाहिए, जहां अवधारणा का वास्तविक विवरण पूरी तरह से टेम्पलेट के कार्यान्वयन द्वारा परिभाषित किया गया है। फ़ंक्शन / वर्ग, और टेम्पलेट के साथ उपयोग किए जाने वाले प्रकार के वर्ग द्वारा नहीं, जो कि OOP का कुछ विरोधी उपयोग है।

उदाहरण के लिए, आप फ़ंक्शन को बता सकते हैं:

void MyFunc(ForwardIterator<...> *I);

अद्यतन: जैसा कि यह मूल प्रश्न में स्पष्ट नहीं था, फ़ॉरवर्डइटरेटर को किसी भी फ़ॉरवर्डेटर प्रकार की अनुमति देने के लिए खुद को टेम्पलेट किया जाना ठीक है। इसके विपरीत एक अवधारणा के रूप में फॉरवर्डिएटर है।

केवल अपनी परिभाषा को देखते हुए एक फॉरवर्ड इटरेटर की अपेक्षा करता है, जहाँ आपको कार्यान्वयन के लिए या प्रलेखन को देखने की आवश्यकता होगी:

template <typename Type> void MyFunc(Type *I);

दो दावे मैं टेम्प्लेट का उपयोग करने के पक्ष में कर सकता हूं: संकलित कोड को अधिक कुशल बनाया जा सकता है, प्रत्येक उपयोग किए गए प्रकार के टेम्प्लेट को संकलित करने के बजाय, vtables का उपयोग करके। और तथ्य यह है कि टेम्प्लेट का उपयोग देशी प्रकारों के साथ किया जा सकता है।

हालांकि, मैं एक और अधिक गहन कारण की तलाश कर रहा हूं कि एसटीएल के लिए टेम्प्लेटिंग के पक्ष में शास्त्रीय ओओपी को क्यों छोड़ा जाए? (यह मानते हुए कि आपने अभी तक पढ़ा: पी)


4
आपको stackoverflow.com/questions/31693/… की जाँच करनी पड़ सकती है । स्वीकृत उत्तर इस बात का एक उत्कृष्ट विवरण है कि आप जेनरिक पर कौन से टेम्पलेट प्रदान करते हैं।
जेम्स मैकमोहन

6
@ जोनास: इसका कोई मतलब नहीं है। कैश पर बाधा घड़ी चक्र की लागत है, यही कारण है कि यह महत्वपूर्ण है। दिन के अंत में, यह घड़ी चक्र है, कैश नहीं है, जो प्रदर्शन को परिभाषित करता है। मेमोरी, और कैश केवल अब तक महत्वपूर्ण है क्योंकि यह खर्च किए गए घड़ी चक्रों को प्रभावित करता है। इसके अलावा, प्रयोग आसानी से किया जा सकता है। तुलना करें, कहें, std :: for_Each को फंक्शनल तर्क के साथ कहा जाता है, समकक्ष OOP / vtable दृष्टिकोण के साथ। प्रदर्शन में अंतर चौंका देने वाला है । जिस कारण टेम्पलेट संस्करण का उपयोग किया जाता है।
जलफ

7
और कोई कारण नहीं है कि निरर्थक कोड icache को भर रहा होगा। यदि मैं अपने कार्यक्रम में वेक्टर <char> और वेक्टर <int> को इंस्टेंट करता हूं, तो वेक्टर <char> कोड को icache में लोड क्यों किया जाना चाहिए, जबकि मैं वेक्टर <int> को प्रोसेस कर रहा हूं? वास्तव में, वेक्टर <int> के लिए कोड को ट्रिम किया जाता है क्योंकि इसमें कास्टिंग, vtables और अप्रत्यक्ष के लिए कोड शामिल करने की आवश्यकता नहीं होती है।
jalf

3
एलेक्स स्टेपानोव बताते हैं कि विरासत और समानता एक साथ अच्छा क्यों नहीं खेलते हैं।
fredoverflow

6
@BerndJendrissek: उम्म, करीबी, लेकिन खुद कोई नहीं। हां, मेमोरी बैंडविड्थ और कैशे उपयोग के संदर्भ में अधिक कोड की लागत अगर यह वास्तव में कभी भी उपयोग की जाती है । लेकिन वहाँ एक उम्मीद की कोई विशेष कारण है vector<int>और vector<char>एक ही समय में प्रयोग की जाने वाली। वे, निश्चित रूप से, लेकिन आप एक ही समय में कोड के किसी भी दो टुकड़ों का उपयोग कर सकते हैं । इसका खाका, C ++ या STL से कोई लेना-देना नहीं है। वहाँ तात्कालिकता में कुछ भी नहीं है vector<int>जिसके लिए vector<char>कोड को लोड करने या निष्पादित करने की आवश्यकता होती है ।
जलफ

जवाबों:


607

संक्षिप्त उत्तर है "क्योंकि C ++ चालू है"। हाँ, 70 के दशक के उत्तरार्ध में, स्ट्रॉस्ट्रुप का इरादा OOP क्षमताओं के साथ उन्नत C बनाने का था, लेकिन यह बहुत समय पहले है। 1998 में जब तक भाषा को मानकीकृत किया गया, तब तक यह एक ओओपी भाषा नहीं थी। यह एक बहु-प्रतिमान भाषा थी। यह निश्चित रूप से OOP कोड के लिए कुछ समर्थन था, लेकिन इसमें एक ट्यूरिंग-पूर्ण टेम्पलेट भाषा भी थी, यह संकलन-समय मेटाप्रोग्रामिंग की अनुमति देता था, और लोगों ने सामान्य प्रोग्रामिंग की खोज की थी। अचानक, OOP सिर्फ इतना महत्वपूर्ण नहीं लगता था। नहीं जब हम टेम्प्लेट और जेनेरिक प्रोग्रामिंग के माध्यम से उपलब्ध तकनीकों का उपयोग करके सरल, अधिक संक्षिप्त और अधिक कुशल कोड लिख सकते हैं ।

OOP पवित्र कब्र नहीं है। यह एक प्यारा विचार है, और यह 70 के दशक में प्रक्रियात्मक भाषाओं पर काफी सुधार था जब इसका आविष्कार किया गया था। लेकिन यह ईमानदारी से नहीं है यह सब होने के लिए टूट गया है। कई मामलों में यह अनाड़ी और वाचाल है और यह वास्तव में पुन: प्रयोज्य कोड या प्रतिरूपकता को बढ़ावा नहीं देता है।

यही कारण है कि सी ++ समुदाय आज जेनेरिक प्रोग्रामिंग में अधिक रुचि रखता है, और हर कोई आखिरकार यह महसूस करना शुरू कर रहा है कि कार्यात्मक प्रोग्रामिंग काफी चतुर है। ओओपी अपने आप में एक सुंदर दृश्य नहीं है।

एक काल्पनिक "OOP-ified" एसटीएल की निर्भरता ग्राफ खींचने की कोशिश करें। कितने वर्गों को एक-दूसरे के बारे में जानना होगा? निर्भरता बहुत होगी । क्या आप सिर्फ vectorहेडर को शामिल कर पाएंगे , वह भी बिना iteratorया iostreamखींचे? एसटीएल यह आसान बनाता है। एक वेक्टर इट्टरेटर प्रकार के बारे में जानता है जो इसे परिभाषित करता है, और यह सब है। एसटीएल एल्गोरिदम कुछ भी नहीं जानते हैं । भले ही वे सभी पुनरावृत्तियों को मापदंडों के रूप में स्वीकार करते हों, उन्हें इट्रेटर हेडर शामिल करने की आवश्यकता नहीं है। फिर कौन सा अधिक मॉड्यूलर है?

एसटीएल ओओपी के नियमों का पालन नहीं कर सकता क्योंकि जावा इसे परिभाषित करता है, लेकिन क्या यह ओओपी के लक्ष्यों को प्राप्त नहीं करता है ? क्या यह पुन: प्रयोज्य, कम युग्मन, प्रतिरूपकता और इनकैप्सुलेशन प्राप्त नहीं करता है?

और क्या यह OOP-ified संस्करण से बेहतर इन लक्ष्यों को प्राप्त नहीं करेगा?

एसटीएल को भाषा में क्यों अपनाया गया, इसके लिए कई चीजें हुईं, जिससे एसटीएल को बढ़ावा मिला।

सबसे पहले, C ++ में टेम्पलेट जोड़े गए थे। उन्हें उसी कारण से जोड़ा गया था जो .NET में जेनेरिक जोड़े गए थे। यह एक अच्छा विचार था कि "टाइप ए के कंटेनर" जैसे सामानों को टाइप सुरक्षा के बिना फेंकने में सक्षम होने के लिए एक अच्छा विचार है। बेशक, वे जिस कार्यान्वयन पर बस गए थे वह काफी अधिक जटिल और शक्तिशाली था।

तब लोगों को पता चला कि उनके द्वारा जोड़ा गया टेम्पलेट तंत्र उम्मीद से भी अधिक शक्तिशाली था। और किसी ने अधिक सामान्य लाइब्रेरी लिखने के लिए टेम्प्लेट का उपयोग करके प्रयोग करना शुरू कर दिया। एक कार्यात्मक प्रोग्रामिंग से प्रेरित है, और एक जो C ++ की सभी नई क्षमताओं का उपयोग करता है।

उन्होंने इसे C ++ भाषा समिति के समक्ष प्रस्तुत किया, जिसने इसका उपयोग करने के लिए काफी समय लिया क्योंकि यह इतना अजीब और अलग दिखता था, लेकिन अंततः यह महसूस किया कि इसने पारंपरिक OOP समकक्षों की तुलना में बेहतर काम किया, अन्यथा उन्हें शामिल करना होगा । इसलिए उन्होंने इसके लिए कुछ समायोजन किया, और इसे मानक पुस्तकालय में अपनाया।

यह एक वैचारिक विकल्प नहीं था, यह "क्या हम ओओपी बनना चाहते हैं या नहीं" का राजनीतिक विकल्प नहीं था, लेकिन बहुत ही व्यावहारिक है। उन्होंने पुस्तकालय का मूल्यांकन किया, और देखा कि यह बहुत अच्छी तरह से काम करता है।

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

C ++ मानक पुस्तकालय को कुशल बनाना होगा। यदि यह तुलना में कम कुशल है, तो कहिए, हाथ से लुढ़का हुआ C कोड, तो लोग इसका उपयोग नहीं करेंगे। इससे उत्पादकता कम होगी, कीड़े होने की संभावना बढ़ेगी, और कुल मिलाकर यह एक बुरा विचार है।

और एसटीएल को आदिम प्रकारों के साथ काम करना पड़ता है, क्योंकि आदिम प्रकार आपके पास सी में हैं, और वे दोनों भाषाओं का एक प्रमुख हिस्सा हैं। यदि एसटीएल ने देशी सरणियों के साथ काम नहीं किया, तो यह बेकार हो जाएगा ।

आपके प्रश्न की एक मजबूत धारणा है कि OOP "सर्वश्रेष्ठ" है। मैं क्यों सुनने को उत्सुक हूं। आप पूछते हैं कि उन्होंने "शास्त्रीय ओओपी को क्यों छोड़ दिया"। मैं सोच रहा हूं कि उन्हें इसके साथ क्यों चिपकना चाहिए था। इसके क्या फायदे होंगे?


22
यह एक अच्छा लेखन है, लेकिन मैं एक विस्तार को उजागर करना चाहूंगा। STL C ++ का "उत्पाद" नहीं है। वास्तव में, STL, एक अवधारणा के रूप में, C ++ से पहले अस्तित्व में था, और C ++ सिर्फ एक कुशल भाषा रही (लगभग) सामान्य प्रोग्रामिंग के लिए पर्याप्त शक्ति है, इसलिए STL C ++ में लिखा गया था।
इगोर क्रिवोकोन

17
चूंकि टिप्पणियां इसे जारी रखती हैं, हां, मुझे पता है कि एसटीएल नाम अस्पष्ट है। लेकिन मैं "सी ++ मानक पुस्तकालय का हिस्सा जो एसटीएल पर मॉडल किया गया है" के लिए एक बेहतर नाम के बारे में नहीं सोच सकता। मानक पुस्तकालय के इस भाग के लिए जिस वास्तविक नाम है , बस "एसटीएल" भले ही यह सख्ती से गलत है। :) जब तक लोग पूरे मानक पुस्तकालय (IOStreams और C stdlib हेडर सहित) के लिए नाम के रूप में STL का उपयोग नहीं करते हैं , मैं खुश हूं। :)
jalf

5
@einpoklum और वास्तव में आप एक सार आधार वर्ग से क्या हासिल करेंगे? std::setएक उदाहरण के रूप में लें । यह एक मूल आधार वर्ग से विरासत में नहीं मिलता है। यह आपके उपयोग को कैसे सीमित करता है std::set? क्या ऐसा कुछ भी नहीं है जो आप नहीं कर सकते std::setक्योंकि यह एक सार आधार वर्ग से विरासत में नहीं मिला है?
fredoverflow

22
@einpoklum कृपया स्मालटाक भाषा पर एक नज़र डालें, जिसे एलन काय ने ओओपी शब्द का आविष्कार करते समय ओओपी भाषा के रूप में डिज़ाइन किया था। इसमें इंटरफेस नहीं था। OOP इंटरफेस या अमूर्त बेस क्लास के बारे में नहीं है। आप कहना है कि "जावा, जो अवधि OOP मन में था के आविष्कारक सी ++ की तुलना में अधिक OOP जो है जैसा कुछ भी नहीं है जा रहे हैं भी तरह क्या अवधि OOP के आविष्कारक मन में था कुछ भी नहीं है"? आपके कहने का मतलब "सी ++ मेरे स्वाद के लिए पर्याप्त नहीं है"। यह उचित है, लेकिन इसका ओओपी से कोई लेना- देना नहीं है।
:

8
@MasonWheeler अगर यह जवाब एक गुच्छा था एक बकवास बकवास है जिसे आप सचमुच दुनिया भर के सैकड़ों डेवलपर्स नहीं देखेंगे, तो इस पर +1 वोटिंग केवल तीन लोग करेंगे अन्यथा
पांडा -34

88

इस बारे में सबसे सीधा जवाब है कि मुझे लगता है कि आप इसके बारे में पूछ / शिकायत कर रहे हैं: यह धारणा कि सी ++ एक ओओपी भाषा है, एक गलत धारणा है।

C ++ एक बहु-प्रतिमान भाषा है। इसे ओओपी सिद्धांतों का उपयोग करके प्रोग्राम किया जा सकता है, इसे प्रक्रियात्मक रूप से प्रोग्राम किया जा सकता है, इसे जेनरिक रूप से (टेम्प्लेट) प्रोग्राम किया जा सकता है, और C ++ 11 (पूर्व में C ++ 0x के रूप में जाना जाता है) के साथ कुछ चीजों को कार्यात्मक रूप से भी प्रोग्राम किया जा सकता है।

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


4
"और C ++ 0x के साथ कुछ चीजों को कार्यात्मक रूप से भी प्रोग्राम किया जा सकता है" - यह उन सुविधाओं के बिना कार्यात्मक रूप से प्रोग्राम किया जा सकता है, बस अधिक मौखिक रूप से।
जोनास कोल्कर

3
@ टायलर वास्तव में अगर आपने C ++ को शुद्ध OOP के लिए विवश किया है, तो आपको ऑब्जेक्टिव-सी के साथ छोड़ दिया जाएगा।
जूल

@TylerMcHenry: अभी-अभी यह पूछे जाने पर , मुझे लगता है कि मैंने आपके समान ही उत्तर दिया है! बस एक बिंदु। काश आप इस तथ्य को जोड़ते कि मानक पुस्तकालय का उपयोग ऑब्जेक्ट-ओरिएंटेड कोड लिखने के लिए नहीं किया जा सकता।
einpoklum

74

मेरी समझ यह है कि स्ट्रॉस्ट्रुप मूल रूप से एक "OOP- स्टाइल" कंटेनर डिजाइन को प्राथमिकता देता था, और वास्तव में इसे करने का कोई अन्य तरीका नहीं देखा था। अलेक्जेंडर स्टेपानोव एसटीएल के लिए जिम्मेदार है, और उसके लक्ष्यों में "इसे वस्तु उन्मुख बनाना" शामिल नहीं था :

वह मूल बिंदु है: एल्गोरिदम को बीजीय संरचनाओं पर परिभाषित किया गया है। मुझे यह महसूस करने में कुछ और साल लग गए कि आपको नियमित स्वयंसिद्धताओं में जटिलता आवश्यकताओं को जोड़कर संरचना की धारणा को आगे बढ़ाना है। ... मेरा मानना ​​है कि कंप्यूटर विज्ञान के लिए पुनरावृत्त सिद्धांत केंद्रीय हैं जैसे कि छल्ले या बानाच स्थान के सिद्धांत गणित के लिए केंद्रीय हैं। हर बार जब मैं एक एल्गोरिथ्म को देखूंगा तो मैं एक संरचना खोजने की कोशिश करूंगा, जिस पर इसे परिभाषित किया गया है। इसलिए मैं जो करना चाहता था वह था एल्गोरिदम का उदारतापूर्वक वर्णन करना। यही मुझे अच्छा लगता है। मैं एक महीने में खर्च कर सकते हैं एक प्रसिद्ध एल्गोरिथ्म पर काम कर रहा है जो इसके सामान्य प्रतिनिधित्व को खोजने की कोशिश कर रहा है। ...

एसटीएल, कम से कम मेरे लिए, एकमात्र तरीका है जो प्रोग्रामिंग संभव है। यह वास्तव में, C ++ प्रोग्रामिंग से काफी अलग है क्योंकि इसे प्रस्तुत किया गया था और अभी भी अधिकांश पाठ्यपुस्तकों में प्रस्तुत किया गया है। लेकिन, आप देखते हैं, मैं सी ++ में प्रोग्राम करने की कोशिश नहीं कर रहा था, मैं सॉफ्टवेयर से निपटने का सही तरीका खोजने की कोशिश कर रहा था। ...

मैंने कई झूठी शुरुआत की थी। उदाहरण के लिए, मैंने विरासत और आभासी लोगों के लिए कुछ उपयोग खोजने की कोशिश में वर्षों बिताए, इससे पहले कि मैं समझ पाता कि उस तंत्र को मौलिक रूप से त्रुटिपूर्ण क्यों किया गया था और इसका उपयोग नहीं किया जाना चाहिए। मुझे बहुत खुशी है कि कोई भी सभी मध्यवर्ती कदम नहीं देख सका - उनमें से अधिकांश बहुत मूर्ख थे।

(वह बताते हैं कि उत्तराधिकार और वर्चुअल्स - उर्फ ​​ऑब्जेक्ट ओरिएंटेड डिज़ाइन "मौलिक रूप से त्रुटिपूर्ण था और इसका उपयोग" बाकी साक्षात्कार में नहीं किया जाना चाहिए)।

एक बार जब स्टेपानोव ने स्ट्रोस्ट्रुप, स्ट्रॉस्ट्रुप और अन्य लोगों को अपनी लाइब्रेरी भेंट की, तो इसे आईएसओ सी ++ मानक (एक ही साक्षात्कार) में प्राप्त करने के लिए भारी प्रयास किए गए:

बज़्ने स्ट्रॉस्ट्रुप का समर्थन महत्वपूर्ण था। बज्ने वास्तव में मानक में एसटीएल चाहता था और अगर बज़्र्न कुछ चाहता है, तो उसे मिल जाता है। ... उन्होंने मुझे एसटीएल में बदलाव करने के लिए भी मजबूर किया जो मैं किसी और के लिए कभी नहीं बनाऊंगा ... वह सबसे ज्यादा दिमाग वाले व्यक्ति हैं जिन्हें मैं जानता हूं। वह काम करवाता है। यह समझने में उन्हें थोड़ी देर लगी कि एसटीएल क्या था, लेकिन जब उन्होंने किया, तो उन्होंने इसे आगे बढ़ाने के लिए तैयार किया। उन्होंने एसटीएल में यह देखने के लिए भी योगदान दिया कि प्रोग्रामिंग का एक से अधिक तरीका मान्य था - एक दशक से अधिक के लिए फ्लैक और प्रचार का कोई अंत नहीं, और लचीलेपन, दक्षता, ओवरलोडिंग और टाइप-सेफ्टी के संयोजन का पीछा करना। टेम्पलेट्स जो STL को संभव बनाती हैं। मैं यह स्पष्ट रूप से बताना चाहूंगा कि बज़्ने मेरी पीढ़ी की प्रमुख भाषा डिजाइनर है।


2
दिलचस्प साक्षात्कार। बहुत यकीन है कि मैंने इसे कुछ समय पहले पढ़ा है, लेकिन निश्चित रूप से फिर से गुजरने लायक था। :)
जुलफ २४'०

3
प्रोग्रामिंग के बारे में सबसे दिलचस्प साक्षात्कारों में से एक जो मैंने कभी पढ़ा है। हालांकि यह मुझे और अधिक विस्तार के लिए प्यास छोड़ रहा है ...
फेलिक्सज़

बहुत सी शिकायतें वह जावा जैसी भाषाओं के बारे में करता है ("आप जावा में एक सामान्य अधिकतम () नहीं लिख सकते हैं जो किसी प्रकार के दो तर्क लेता है और उसी प्रकार का रिटर्न मान है") केवल बहुत प्रारंभिक संस्करणों के लिए प्रासंगिक थे भाषा से पहले, जेनेरिक जोड़े गए थे। यहां तक ​​कि शुरुआत से, यह ज्ञात था कि अंत में जेनेरिक जोड़ा जाएगा, हालांकि (एक बार एक व्यवहार्य वाक्य रचना / शब्दार्थ का पता लगा लिया गया था), इसलिए उनकी आलोचनाएं काफी हद तक निराधार हैं। हां, किसी रूप में सामान्य रूप से टाइप की भाषा में सुरक्षा को बनाए रखने के लिए जेनेरिक की जरूरत होती है, लेकिन नहीं, इससे OO को बेकार नहीं बनाया जाता है।
कुछ लड़के

1
@SomeGuy वे Java प्रति se के बारे में शिकायत नहीं कर रहे हैं। वह स्मॉलटॉक के "मानक" ओओ प्रोग्रामिंग के बारे में बात कर रहा है या, जावा कह रहा है । साक्षात्कार 90 के दशक के अंत से है (उन्होंने SGI में काम करने का उल्लेख किया है, जिसे उन्होंने 2000 में AT & T में काम करने के लिए छोड़ दिया था)। जेनरिक केवल 2004 में जावा में संस्करण 1.5 में जोड़े गए थे और वे "मानक" ओओ मॉडल से विचलन हैं।
19

24

एसटीएल के लेखक स्टेपानोव के साथ इस साक्षात्कार में उत्तर मिला है :

हाँ। STL ऑब्जेक्ट ओरिएंटेड नहीं है। मुझे लगता है कि आर्टिफिशियल इंटेलिजेंस के रूप में ऑब्जेक्ट ओरिएंटेशन लगभग एक धोखा जैसा है। मुझे अभी तक एक दिलचस्प कोड कोड देखना है जो इन OO लोगों से आता है।


अच्छा रत्न; क्या आप जानते हैं कि यह किस वर्ष से है?
कोस

2
@Kos, web.archive.org/web/20000607205939/http://www.stlport.org/… के अनुसार, लिंक किए गए पृष्ठ का पहला संस्करण 7 जून 2001 से है। नीचे की ओर स्थित पृष्ठ का कहना है कि कॉपीराइट 2001- 2008।
alfC

@Kos Stepanov ने पहले उत्तर में SGI में काम करने का उल्लेख किया है। उन्होंने मई 2000 में SGI छोड़ दिया, इसलिए संभवतः साक्षात्कार इससे पुराना है।
melpomene

18

डेटा संरचना और एल्गोरिदम लाइब्रेरी के लिए शुद्ध OOP डिज़ाइन बेहतर क्यों होगा! ओओपी हर चीज का हल नहीं है।

IMHO, STL सबसे सुंदर पुस्तकालय है जिसे मैंने कभी देखा है :)

आपके प्रश्न के लिए,

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

आपको तथाकथित शुद्ध OOP भाषाओं की गंदा मान्यताओं को छिपाने के लिए बॉक्सिंग और अनबॉक्सिंग जैसी बेवकूफी वाली चीज़ की ज़रूरत है।

एकमात्र समस्या जो मुझे एसटीएल के साथ दिखाई देती है, और सामान्य रूप से टेम्प्लेट भयानक त्रुटि संदेश है। जिसे C ++ 0X में अवधारणाओं का उपयोग करके हल किया जाएगा।

जावा में STL की तुलना कलेक्शंस से करना ताजमहल की मेरे घर से तुलना करने जैसा है :)


12
क्या, ताजमहल छोटा और भव्य है, और आपका घर पहाड़ का आकार, और पूरी तरह से गड़बड़ है? ;)
jalf

अवधारणाएं अब c ++ 0x का हिस्सा नहीं हैं। त्रुटि संदेशों में से कुछ static_assertशायद का उपयोग कर पूर्व खाली किया जा सकता है ।
KitsuneYMG

जीसीसी 4.6 ने टेम्पलेट त्रुटि संदेशों में सुधार किया है, और मेरा मानना ​​है कि 4.7+ इसके साथ भी बेहतर हैं।
डेविड स्टोन

एक अवधारणा अनिवार्य रूप से "इंटरफ़ेस" है जिसे ओपी पूछ रहा था। एकमात्र अंतर यह है कि एक अवधारणा से "विरासत" निहित है (यदि एक वर्ग में सभी सही सदस्य फ़ंक्शन हैं, तो यह स्पष्ट रूप से होने के बजाय स्वचालित रूप से अवधारणा का एक उपप्रकार है) (एक जावा वर्ग को स्पष्ट रूप से घोषित करना होगा कि वह एक इंटरफ़ेस लागू करता है) । हालाँकि, निहित और स्पष्ट दोनों उप-योग मान्य OO हैं, और कुछ OO भाषाओं में निहित विरासत है जो अवधारणाओं की तरह ही काम करती है। तो यहाँ जो कहा जा रहा है वह मूल रूप से "OO बेकार है: टेम्पलेट्स का उपयोग करें। लेकिन टेम्पलेट्स में समस्याएं हैं, इसलिए अवधारणाओं (जो OO हैं) का उपयोग करें।"
कुछ लड़के

11

टेम्प्लेटेड प्रकारों को एक "अवधारणा" का पालन करना चाहिए (इनपुट Iterator, फॉरवर्ड Iterator, आदि ...) जहां अवधारणा का वास्तविक विवरण पूरी तरह से टेम्पलेट फ़ंक्शन / वर्ग के कार्यान्वयन द्वारा परिभाषित किया गया है, और प्रकार के वर्ग द्वारा नहीं टेम्पलेट के साथ उपयोग किया जाता है, जो OOP का कुछ विरोधी उपयोग है।

मुझे लगता है कि आप टेम्प्लेट द्वारा अवधारणाओं के उपयोग को गलत समझते हैं। फॉरवर्ड इटरेटर, उदाहरण के लिए, एक बहुत अच्छी तरह से परिभाषित अवधारणा है। उन भावों को खोजने के लिए जो एक वर्ग के लिए फॉरवर्ड इटरेटर के रूप में मान्य होने चाहिए, और कम्प्यूटेशनल जटिलता सहित उनके शब्दार्थ, आप मानक को देखते हैं या http://www.sgi.com/tech/stl/ForwardIterator.html पर (आपको यह सब देखने के लिए इनपुट, आउटपुट और ट्रिवियल इटरेटर के लिंक का पालन करना होगा)।

वह दस्तावेज़ एक पूरी तरह से अच्छा इंटरफ़ेस है, और "अवधारणा का वास्तविक विवरण" वहीं पर परिभाषित किया गया है। वे फॉरवर्ड Iterators के कार्यान्वयन द्वारा परिभाषित नहीं हैं, और न ही वे एल्गोरिदम द्वारा परिभाषित किए गए हैं जो फॉरवर्ड Iterators का उपयोग करते हैं।

एसटीएल और जावा के बीच इंटरफेस कैसे संभाला जाता है, इसके अंतर तीन गुना हैं:

1) एसटीएल ऑब्जेक्ट का उपयोग करके वैध अभिव्यक्तियों को परिभाषित करता है, जबकि जावा उन तरीकों को परिभाषित करता है जो ऑब्जेक्ट पर कॉल करने योग्य होना चाहिए। बेशक एक वैध अभिव्यक्ति एक विधि (सदस्य फ़ंक्शन) कॉल हो सकती है, लेकिन यह होना जरूरी नहीं है।

2) जावा इंटरफेस रनटाइम ऑब्जेक्ट हैं, जबकि एसटीएल अवधारणाएं आरटीटीआई के साथ भी रनटाइम पर दिखाई नहीं देती हैं।

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

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

C ++ में, Python की तरह, शब्दार्थ और वाक्यविन्यास दोनों निहित हैं, हालांकि C ++ (और Python में यदि आपको मजबूत-टाइपिंग प्रीप्रोसेसर मिलता है) तो आपको कंपाइलर से कुछ मदद मिलती है। यदि किसी प्रोग्रामर को कार्यान्वयन वर्ग द्वारा इंटरफेस जैसे जावा की स्पष्ट घोषणा की आवश्यकता होती है, तो मानक दृष्टिकोण प्रकार के लक्षणों का उपयोग करना है (और कई विरासत इस क्रिया को रोक सकते हैं)। जावा के साथ तुलना में क्या कमी है, एक एकल टेम्पलेट है जिसे मैं अपने प्रकार के साथ त्वरित कर सकता हूं, और जो कि केवल और केवल तभी संकलित करेगा यदि सभी आवश्यक अभिव्यक्तियाँ मेरे प्रकार के लिए मान्य हैं। यह मुझे बताएगा कि क्या मैंने सभी आवश्यक बिट्स को लागू किया है, "इससे पहले कि मैं इसका उपयोग करूं"। यह एक सुविधा है, लेकिन यह OOP का मूल नहीं है (और यह अभी भी शब्दार्थ का परीक्षण नहीं करता है,

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

आप फ़ंक्शन को बता सकते हैं ... अपनी परिभाषा को देखकर ही फॉरवर्ड इटरेटर की अपेक्षा करता है, जहाँ आपको कार्यान्वयन के लिए या दस्तावेज़ देखने की आवश्यकता होगी ...

व्यक्तिगत रूप से मुझे लगता है कि निहित प्रकार एक ताकत है, जब उचित रूप से उपयोग किया जाता है। एल्गोरिदम कहता है कि यह अपने टेम्पलेट मापदंडों के साथ क्या करता है, और कार्यान्वयनकर्ता यह सुनिश्चित करता है कि वे चीजें काम करती हैं: यह बिल्कुल सामान्य भाजक है जो "इंटरफेस" को करना चाहिए। इसके अलावा, STL के साथ, आप std::copyहेडर फ़ाइल में इसके आगे की घोषणा को खोजने के आधार पर , उपयोग करने की संभावना नहीं रखते हैं । प्रोग्रामर को काम करना चाहिए , जो फ़ंक्शन प्रलेखन पर आधारित है, न कि केवल फ़ंक्शन हस्ताक्षर पर। यह C ++, Python, या Java में सही है। किसी भी भाषा में टाइपिंग के साथ क्या हासिल किया जा सकता है, इस पर सीमाएं हैं, और कुछ ऐसा करने के लिए टाइपिंग का उपयोग करने की कोशिश नहीं करता (चेक शब्दार्थ) एक त्रुटि होगी।

उस ने कहा, एसटीएल एल्गोरिदम आमतौर पर अपने टेम्पलेट मापदंडों को एक तरह से नाम देते हैं जो यह स्पष्ट करता है कि अवधारणा की आवश्यकता क्या है। हालांकि यह दस्तावेज़ीकरण की पहली पंक्ति में उपयोगी अतिरिक्त जानकारी प्रदान करना है, न कि आगे की घोषणाओं को अधिक जानकारीपूर्ण बनाना। पैरामीटर के प्रकारों में एनकैप्सुलेट किए जा सकने के लिए आपको और भी बहुत सी चीजें हैं, इसलिए आपको डॉक्स पढ़ना होगा। (उदाहरण के लिए एल्गोरिदम में जो एक इनपुट रेंज और एक आउटपुट इटरेटर लेते हैं, संभावना है कि इनपुट रेंज के आकार के आधार पर आउटपुट की एक निश्चित संख्या के लिए आउटपुट इटिटर को पर्याप्त "स्पेस" की आवश्यकता होती है और हो सकता है कि उसमें वेल्यू बहुत ज्यादा हो। )

यहाँ स्पष्ट रूप से घोषित इंटरफेस पर Bjarne है: http://www.artima.com/cppsource/cpp0xP.html

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

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


स्पष्ट रूप से घोषित इंटरफेस पर, दो शब्द: प्रकार की कक्षाएं। (जो पहले से ही "अवधारणा" से स्टेपानोव का मतलब है।)
pyon

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

सच है, मैं "वैध" शब्द के साथ तेज और ढीला खेल रहा था। मेरा सिर्फ यह मतलब था कि यदि कंपाइलर आवश्यक अभिव्यक्तियों में से किसी एक को संकलित नहीं कर सकता है, तो यह कुछ रिपोर्ट करेगा।
स्टीव जेसोप

8

"ओओपी टू का मतलब केवल मैसेजिंग, स्थानीय प्रतिधारण और संरक्षण और राज्य-प्रक्रिया का छिपाना, और सभी चीजों का चरम देर-बंधन है। यह स्मालटाक और एलआईएसपी में किया जा सकता है। संभवतः अन्य प्रणालियां हैं जिनमें यह संभव है, लेकिन मैं उनके बारे में नहीं जानता। ” - एलन के, स्मॉलटाक के निर्माता।

C ++, Java और अन्य सभी भाषाएँ शास्त्रीय OOP से बहुत दूर हैं। यह कहा, विचारधाराओं के लिए बहस बहुत उत्पादक नहीं है। सी ++ किसी भी मायने में शुद्ध नहीं है, इसलिए यह कार्यक्षमता को लागू करता है जो उस समय व्यावहारिक समझ बनाने के लिए लगता है।


7

एसटीएल ने सबसे अधिक इस्तेमाल किए जाने वाले एल्गोरिदम को कवर करने के लिए एक बड़ा पुस्तकालय प्रदान करने के इरादे से शुरू किया था - जो कि व्यवहार और प्रदर्शन के लक्ष्य के साथ है । टेम्पलेट उस कार्यान्वयन और लक्ष्य को संभव बनाने के लिए एक महत्वपूर्ण कारक के रूप में आया था।

बस एक और संदर्भ प्रदान करने के लिए:

अल स्टीवंस साक्षात्कार डीडीजे के मार्च 1995 में एलेक्स स्टेपानोव:

स्टेपानोव ने अपने कार्य अनुभव और एल्गोरिथ्म के एक बड़े पुस्तकालय की ओर बनाए गए विकल्प को समझाया, जो अंततः एसटीएल में विकसित हुआ।

जेनेरिक प्रोग्रामिंग में आपकी दीर्घकालिक रुचि के बारे में कुछ बताएं

..... तब मुझे C ++ पुस्तकालयों पर C ++ समूह में काम करने वाले Bell Laboratories में नौकरी की पेशकश की गई थी। उन्होंने मुझसे पूछा कि क्या मैं इसे C ++ में कर सकता हूं। बेशक, मैं सी ++ नहीं जानता था और निश्चित रूप से, मैंने कहा कि मैं कर सकता था। लेकिन मैं इसे C ++ में नहीं कर सका, क्योंकि 1987 में C ++ में टेम्पलेट नहीं थे, जो प्रोग्रामिंग की इस शैली को सक्षम करने के लिए आवश्यक हैं। आनुवंशिकता प्राप्त करने के लिए वंशानुक्रम ही एकमात्र तंत्र था और यह पर्याप्त नहीं था।

अब भी C ++ वंशानुक्रम जेनेरिक प्रोग्रामिंग के लिए ज्यादा काम का नहीं है। आइए चर्चा करें कि क्यों। कई लोगों ने डेटा संरचनाओं और कंटेनर कक्षाओं को लागू करने के लिए विरासत का उपयोग करने का प्रयास किया है। जैसा कि हम अब जानते हैं, अगर कोई सफल प्रयास थे तो कुछ ही थे। सी ++ विरासत, और इसके साथ जुड़े प्रोग्रामिंग शैली नाटकीय रूप से सीमित हैं। एक डिजाइन को लागू करना असंभव है जिसमें तुच्छता का उपयोग करना समानता के रूप में शामिल है। यदि आप अपने पदानुक्रम की जड़ में एक बेस क्लास X से शुरू करते हैं और इस क्लास पर एक वर्चुअल समानता ऑपरेटर को परिभाषित करते हैं जो X का तर्क लेता है, तो X से क्लास Y की व्युत्पत्ति करें। समानता का इंटरफ़ेस क्या है? इसमें समानता है जो वाई के साथ एक्स की तुलना करता है। उदाहरण के रूप में जानवरों का उपयोग करना (ओओ लोग लोगों को जानवरों से प्यार करते हैं), स्तनपायी को परिभाषित करते हैं और स्तनपायी से जिराफ प्राप्त करते हैं। फिर एक सदस्य फ़ंक्शन दोस्त को परिभाषित करें, जहां जानवर जानवर के साथ घूमता है और जानवर को वापस करता है। फिर आप जिराफ को जानवर से निकालते हैं और निश्चित रूप से, इसका एक फंक्शन मेट होता है जहां जिराफ जानवर के साथ रहता है और एक जानवर को वापस करता है। यह निश्चित रूप से नहीं है कि आप क्या चाहते हैं। जबकि संभोग C ++ प्रोग्रामर के लिए बहुत महत्वपूर्ण नहीं हो सकता है, समानता है। मुझे एक भी एल्गोरिथ्म का पता नहीं है जहां किसी प्रकार की समानता का उपयोग नहीं किया जाता है।


5

के साथ बुनियादी समस्या

void MyFunc(ForwardIterator *I);

यह है कि आप सुरक्षित रूप से उस वस्तु का प्रकार कैसे प्राप्त करते हैं जो पुनरावृत्ति करता है? टेम्पलेट्स के साथ, यह आपके लिए संकलन समय पर किया जाता है।


1
ठीक है, मैं या तो: 1. इसे प्राप्त करने का प्रयास न करें, क्योंकि मैं सामान्य कोड लिख रहा हूं। या, 2. इन दिनों जो भी प्रतिबिंब तंत्र C ++ प्रदान करता है, उसका उपयोग करें।
ईनपोकलुम

2

एक क्षण के लिए, आइए मानक पुस्तकालय को मूल रूप से संग्रह और एल्गोरिदम का डेटाबेस समझें।

यदि आपने डेटाबेस के इतिहास का अध्ययन किया है, तो आप निस्संदेह जानते हैं कि शुरुआत में, डेटाबेस ज्यादातर "पदानुक्रमित" थे। पदानुक्रमित डेटाबेस शास्त्रीय OOP के साथ बहुत निकटता से जुड़े हैं - विशेष रूप से, एकल-वंशीय विविधता, जैसे कि स्मॉलटाक द्वारा उपयोग किया जाता है।

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

इसलिए, उन्होंने नेटवर्क मॉडल डेटाबेस का आविष्कार किया। नेटवर्क मॉडल डेटाबेस कई विरासत के बहुत करीब से मेल खाते हैं। सी ++ पूरी तरह से कई विरासत का समर्थन करता है, जबकि जावा एक सीमित रूप का समर्थन करता है (आप केवल एक वर्ग से विरासत में प्राप्त कर सकते हैं, लेकिन आप जितने चाहें उतने इंटरफेस भी लागू कर सकते हैं)।

दोनों पदानुक्रमित मॉडल और नेटवर्क मॉडल डेटाबेस ज्यादातर सामान्य प्रयोजन के उपयोग से फीका हो गए हैं (हालांकि कुछ काफी विशिष्ट niches में रहते हैं)। अधिकांश उद्देश्यों के लिए, उन्हें रिलेशनल डेटाबेस द्वारा प्रतिस्थापित किया गया है।

संबंधपरक डेटाबेस के अधिकांश कारण बहुमुखी प्रतिभा थे। संबंधपरक मॉडल कार्यात्मक रूप से नेटवर्क मॉडल का एक सुपरसेट है (जो बदले में, पदानुक्रमित मॉडल का एक सुपरसेट) है।

C ++ ने काफी हद तक उसी पथ का अनुसरण किया है। एकल वंशानुक्रम और पदानुक्रमित मॉडल के बीच और कई वंशानुक्रम और नेटवर्क मॉडल के बीच पत्राचार काफी स्पष्ट है। C ++ टेम्प्लेट और पदानुक्रमित मॉडल के बीच पत्राचार कम स्पष्ट हो सकता है, लेकिन यह वैसे भी काफी करीब है।

मैंने इसका औपचारिक प्रमाण नहीं देखा है, लेकिन मेरा मानना ​​है कि टेम्प्लेट की क्षमताएं एकाधिक वंशानुक्रम (जो स्पष्ट रूप से सिंगल इनरहाइटेंस का सुपरसेट है) द्वारा प्रदान की गई हैं। एक मुश्किल हिस्सा यह है कि टेम्पलेट्स ज्यादातर सांख्यिकीय रूप से बाध्य होते हैं - अर्थात, सभी बाध्यकारी संकलन समय पर होते हैं, समय नहीं चलाते हैं। इस प्रकार, एक औपचारिक प्रमाण जो वंशानुक्रम विरासत की क्षमताओं का सुपरसेट प्रदान करता है, वह कुछ हद तक कठिन और जटिल हो सकता है (या असंभव भी हो सकता है)।

किसी भी मामले में, मुझे लगता है कि अधिकांश वास्तविक कारण C ++ अपने कंटेनरों के लिए विरासत का उपयोग नहीं करता है - ऐसा करने का कोई वास्तविक कारण नहीं है, क्योंकि विरासत केवल टेम्पलेट्स द्वारा प्रदान की गई क्षमताओं का एक सबसेट प्रदान करता है। चूंकि कुछ मामलों में टेम्प्लेट मूल रूप से एक आवश्यकता है, इसलिए वे लगभग हर जगह उपयोग किए जा सकते हैं।


0

आप फारवर्डइटर के साथ तुलना कैसे करते हैं? यही है, यदि आपके पास वह आइटम है जो आप देख रहे हैं, या आपने इसे पास कर लिया है, तो आप कैसे जांचेंगे?

ज्यादातर समय, मैं कुछ इस तरह का उपयोग करेगा:

void MyFunc(ForwardIterator<MyType>& i)

जिसका अर्थ है कि मुझे पता है कि मैं MyType की ओर इशारा कर रहा हूं, और मैं जानता हूं कि उन लोगों की तुलना कैसे की जाए। हालांकि यह एक टेम्पलेट की तरह दिखता है, यह वास्तव में (कोई "टेम्पलेट" कीवर्ड) नहीं है।


आप बस <,> और = प्रकार के ऑपरेटरों का उपयोग कर सकते हैं और यह नहीं जान सकते कि वे क्या हैं (हालांकि यह वह नहीं हो सकता है जिसका आप मतलब है)
lhahne

संदर्भ के आधार पर, उन लोगों को कोई मतलब नहीं हो सकता है, या वे ठीक काम कर सकते हैं। MyType के बारे में अधिक जानकारी के बिना बताना मुश्किल है, जो कि, संभव है, उपयोगकर्ता करता है, और हम नहीं करते हैं।
टंकटालस

0

इस सवाल के कई बेहतरीन जवाब हैं। यह भी उल्लेख किया जाना चाहिए कि टेम्पलेट एक खुले डिजाइन का समर्थन करते हैं। ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग लैंग्वेज की वर्तमान स्थिति के साथ, किसी को इस तरह की समस्याओं से निपटने के दौरान विज़िटर पैटर्न का उपयोग करना पड़ता है, और सही OOP को कई डायनेमिक बाइंडिंग का समर्थन करना चाहिए। C ++, P. Pirkelbauer, et.al के लिए ओपन मल्टी-विधियाँ देखें बहुत ही इंटरस्टिंग पढ़ने के लिए।

टेम्पलेट्स का एक और दिलचस्प बिंदु यह है कि उनका उपयोग रनटाइम पॉलीमोर्फिज़्म के लिए भी किया जा सकता है। उदाहरण के लिए

template<class Value,class T>
Value euler_fwd(size_t N,double t_0,double t_end,Value y_0,const T& func)
    {
    auto dt=(t_end-t_0)/N;
    for(size_t k=0;k<N;++k)
        {y_0+=func(t_0 + k*dt,y_0)*dt;}
    return y_0;
    }

सूचना है कि इस समारोह भी काम करता है, तो होगा Valueकिसी तरह का एक वेक्टर है ( नहीं std :: वेक्टर, जो बुलाया जाना चाहिए std::dynamic_arrayसे बचने के भ्रम को)

यदि funcछोटा है, तो यह फ़ंक्शन इनलाइनिंग से बहुत लाभ प्राप्त करेगा। उदाहरण उपयोग

auto result=euler_fwd(10000,0.0,1.0,1.0,[](double x,double y)
    {return y;});

इस मामले में, आपको सटीक उत्तर (2.718 ...) पता होना चाहिए, लेकिन प्राथमिक समाधान के बिना एक सरल ODE का निर्माण करना आसान है (संकेत: y में एक बहुपद का उपयोग करें)।

अब, आपके पास एक बड़ी अभिव्यक्ति है func, और आप कई स्थानों पर ODE सॉल्वर का उपयोग करते हैं, इसलिए आपका निष्पादन योग्य हर जगह टेम्प्लेट इंस्टेंटेशन के साथ प्रदूषित हो जाता है। क्या करें? पहली बात यह है कि एक नियमित कार्य सूचक काम करता है। फिर आप क्यूरिंग जोड़ना चाहते हैं ताकि आप एक इंटरफ़ेस और एक स्पष्ट तात्कालिकता लिख ​​सकें

class OdeFunction
    {
    public:
        virtual double operator()(double t,double y) const=0;
    };

template
double euler_fwd(size_t N,double t_0,double t_end,double y_0,const OdeFunction& func);

लेकिन उपरोक्त तात्कालिकता केवल इसके लिए काम करती है double, इंटरफ़ेस को टेम्पलेट के रूप में क्यों न लिखें:

template<class Value=double>
class OdeFunction
    {
    public:
        virtual Value operator()(double t,const Value& y) const=0;
    };

और कुछ सामान्य मूल्य प्रकारों के लिए विशेषज्ञ:

template double euler_fwd(size_t N,double t_0,double t_end,double y_0,const OdeFunction<double>& func);

template vec4_t<double> euler_fwd(size_t N,double t_0,double t_end,vec4_t<double> y_0,const OdeFunction< vec4_t<double> >& func); // (Native AVX vector with four components)

template vec8_t<float> euler_fwd(size_t N,double t_0,double t_end,vec8_t<float> y_0,const OdeFunction< vec8_t<float> >& func); // (Native AVX vector with 8 components)

template Vector<double> euler_fwd(size_t N,double t_0,double t_end,Vector<double> y_0,const OdeFunction< Vector<double> >& func); // (A N-dimensional real vector, *not* `std::vector`, see above)

यदि फ़ंक्शन पहले एक इंटरफ़ेस के आसपास डिज़ाइन किया गया था, तो आपको उस एबीसी से विरासत में मिला होगा। अब आपके पास यह विकल्प है, साथ ही फ़ंक्शन पॉइंटर, लैम्ब्डा, या किसी अन्य फ़ंक्शन ऑब्जेक्ट। यहाँ कुंजी यह है कि हमारे पास होना चाहिए operator()(), और हम इसके वापसी प्रकार पर कुछ अंकगणितीय ऑपरेटरों का उपयोग करने में सक्षम होना चाहिए। इस प्रकार, यदि C ++ में ऑपरेटर ओवरलोडिंग नहीं होता तो टेम्पलेट मशीनरी इस मामले में टूट जाती।


-1

इंटरफ़ेस को इंटरफ़ेस से अलग करने और कार्यान्वयन को स्वैप करने में सक्षम होने की अवधारणा ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग के लिए आंतरिक नहीं है। मेरा मानना ​​है कि यह एक ऐसा विचार है जो माइक्रोसॉफ्ट कॉम जैसे घटक-आधारित विकास में रचा गया था। ( घटक-चालित विकास क्या है, इस पर मेरा उत्तर देखें ?) सी ++ बढ़ने और सीखने, लोगों को विरासत और बहुरूपता से बाहर रखा गया। यह तब तक नहीं था जब तक कि 90 के दशक के लोगों ने "प्रोग्राम टू ए 'इंटरफ़ेस' न कहना शुरू कर दिया हो, न कि 'इंप्लीमेंटेशन' और" फेवरेट 'ऑब्जेक्ट कंपोज़िशन' ओवर क्लास इनहेरिटेंस '। (जिस तरह से दोनों GoF से उद्धृत)।

तब जावा बिल्ट-इन कचरा कलेक्टर और interfaceकीवर्ड के साथ आया , और अचानक यह वास्तव में अलग इंटरफ़ेस और कार्यान्वयन के लिए व्यावहारिक हो गया। इससे पहले कि आप जानते हैं कि यह विचार OO का हिस्सा बन गया। C ++, टेम्प्लेट, और STL इन सब से पहले की तरह है।


सहमत हैं कि इंटरफेस सिर्फ OO नहीं हैं। लेकिन प्रकार प्रणाली में क्षमता बहुरूपता है (यह 60 के दशक में सिमूला में था)। मॉड्यूल इंटरफेस मोडुला -2 और एडा में मौजूद थे, लेकिन ये मेरे विचार से अलग प्रकार की प्रणाली में संचालित होते हैं।
एंडग्विन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.