2009-08-21 6 views
6

जाहिर है (कम से कम gcc -std=c99 के अनुसार) सी 99 फ़ंक्शन ओवरलोडिंग का समर्थन नहीं करता है। सी में कुछ नई सुविधा का समर्थन नहीं करने का कारण आमतौर पर पिछड़ा संगतता है, लेकिन इस मामले में मैं एक ऐसे मामले के बारे में नहीं सोच सकता जिसमें फ़ंक्शन ओवरलोडिंग पिछड़े संगतता को तोड़ देगी। इस बुनियादी सुविधा को शामिल करने के पीछे तर्क क्या है?क्या कोई कारण है कि सी 99 फ़ंक्शन ओवरलोडिंग का समर्थन नहीं करता है?

+2

यदि आप फ़ंक्शन ओवरलोडिंग के साथ सी चाहते हैं, तो आपको C++ को देखने में रुचि हो सकती है। – SingleNegationElimination

+0

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

+0

(http://www.lysator.liu.se/c/rat/c3.html#3-3-2-2 से) –

उत्तर

27

समझने के लिए कि आपको सी में ओवरलोडिंग देखने की संभावना क्यों नहीं है, यह बेहतर तरीके से सीखने में मदद कर सकता है कि सी ++ द्वारा ओवरलोडिंग को कैसे संभाला जाता है।

कोड संकलित करने के बाद, लेकिन इससे पहले कि यह दौड़ने के लिए तैयार हो, इंटरमीडिएट ऑब्जेक्ट कोड लिंक होना चाहिए। यह संकलित कार्यों और अन्य ऑब्जेक्ट्स के किसी न किसी डेटाबेस को लोड/रन बाइनरी फ़ाइल के लिए तैयार करता है। यह अतिरिक्त कदम महत्वपूर्ण है क्योंकि यह संकलित कार्यक्रमों के लिए उपलब्ध मॉड्यूलरिटी का सिद्धांत तंत्र है। यह चरण आपको मौजूदा पुस्तकालयों से कोड लेने और अपने स्वयं के एप्लिकेशन तर्क के साथ मिश्रण करने की अनुमति देता है।

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

सी में, कार्यों लिंकर के लिए प्रतीक नाम हो जाते हैं, इसलिए जब आप लिखना

int main(int argc, char **argv) { return 1; } 

संकलक वस्तु कोड है, जो एक वस्तु main कहा जाता है का एक संग्रह प्रदान करता है।

यह अच्छी तरह से काम करता है, लेकिन इसका मतलब है कि आपके पास एक ही नाम के साथ दो ऑब्जेक्ट नहीं हो सकते हैं, क्योंकि लिंकर यह तय करने में असमर्थ होगा कि इसका किस नाम का उपयोग करना चाहिए। लिंकर तर्क प्रकारों के बारे में कुछ भी नहीं जानता है, और सामान्य रूप से कोड के बारे में बहुत कम है।

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

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

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

मुझे लगता है कि सी को किसी भी सुविधा का पीछा करने की संभावना नहीं है जो कोड उत्पन्न करेगा जो सी ++ के साथ बातचीत करना मुश्किल है।

संपादित: Imagist पूछते हैं:

यह वास्तव में कम पोर्टेबल या अधिक कठिन एक समारोह के साथ बातचीत करने के लिए यदि आप पूर्णांक मुख्य संकल्प लिया होगा (int argc, char ** argv) मुख्य (और यह मानक का हिस्सा थे) के बजाय मुख्य-int-int-char ** जैसे कुछ (? मुझे यहां कोई समस्या नहीं दिख रही है। वास्तव में, मुझे लगता है कि यह आप अधिक जानकारी (जो अनुकूलन के लिए इस्तेमाल किया जा सकता और इस तरह)

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

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

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

साथ ही, यह व्यावहारिक रूप से एक मानक अभ्यास है जो कई समान नामित सी कार्यों को परिभाषित करता है जो केवल तर्कों के रूप में भिन्न होते हैं। इस के एक लंबे उदाहरण के लिए, OpenGL namespace.

+1

यदि आप 'मुख्य मुख्य (int argc, char ** argv) 'को' मुख्य-int-int-char ** 'जैसे किसी मुख्य चीज़ के बजाय' मुख्य मुख्य (int argc, char ** argv) 'हल करते हैं, तो यह वास्तव में कम पोर्टेबल या किसी फ़ंक्शन के साथ बातचीत करने में अधिक कठिन होगा। '(और यह मानक का हिस्सा थे)? मुझे यहां कोई समस्या नहीं दिख रही है। वास्तव में, मुझे ऐसा लगता है कि यह आपको * अधिक * जानकारी देता है (जिसका उपयोग अनुकूलन और इसी तरह के लिए किया जा सकता है)। – Imagist

+0

@Imagist - यह एक भाषा के लिए उपयोगी होगा। यह तुरंत नए सी कोड द्वारा उपयोग किए जाने वाले सभी पुराने सी पुस्तकालयों को प्रस्तुत करेगा, और पुराने सी कोड द्वारा उपयोग किए जाने वाले सभी नए सी पुस्तकालयों को भी लागू किया जाएगा। –

+0

@ क्रिस लुट्ज़ ट्रू, लेकिन एक भाषा डिजाइनर के रूप में आपको कभी-कभी पिछड़े संगतता को तोड़ने के लिए तैयार रहना होगा। सी जैसी भाषा के साथ अक्सर ऐसा नहीं होना चाहिए, लेकिन क्या हर दस साल में पूछने के लिए इतना कुछ है? कई मामलों में हम डिजाइन के फैसले से फंस गए हैं जो कि अच्छा हो सकता है, लेकिन अब आपकी मानसिकता के कारण अच्छा नहीं है। – Imagist

19

जब आप एक सी स्रोत संकलित करते हैं, तो प्रतीक नाम बरकरार रहेगा। यदि आप फ़ंक्शन ओवरलोडिंग को पेश करते हैं, तो आपको नाम झड़पों को रोकने के लिए एक नाम मैंगलिंग तकनीक प्रदान करनी चाहिए। नतीजतन, सी ++ की तरह, आपके पास संकलित बाइनरी में मशीन जेनरेट प्रतीक नाम होंगे।

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

+0

ऐसा लगता है कि इसका उत्तर सरल है: मानक नाम मैंगलिंग तकनीक प्रदान करें प्रकार की जानकारी रखने के लिए। कुछ 'foo (bar) -> foo-bar' और' foo (baz) -> foo-baz' को लागू करना मुश्किल नहीं है। – Imagist

+2

मैंने वास्तव में तीन बिंदुओं का उल्लेख किया: 1. कमजोर टाइपिंग 2. जटिलता में वृद्धि 3. नाम संघर्ष। आप मानक नाम मैंगलिंग तकनीक का निर्माण कर सकते हैं लेकिन आप इसे सी 8 9 के तहत पहले से संकलित पुस्तकालयों के साथ कैसे संगत बनाएंगे और यदि आप सी 99 में लाइब्रेरी बनाते हैं, तो आप इसे C89 में कैसे उपयोग कर सकते हैं? –

6

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

सामान्य रूप से, सी 99 का उद्देश्य मौजूदा अभ्यास के साथ काफी हद तक संगत एक मामूली संशोधन होना था। ओवरलोडिंग एक बहुत बड़ा प्रस्थान किया गया होगा।

+1

मेरे समेत कई भाषा डिजाइनर, सोचते हैं कि पॉइंटर्स के माध्यम से स्मृति तक सीधी पहुंच के परिणामस्वरूप कोड को समझना मुश्किल हो सकता है। समाधान स्पष्ट रूप से भाषा से पॉइंटर्स को बाहर नहीं करना है (कम से कम सी के मामले में नहीं)। – Imagist

+0

@Imagist। मैं आपसे सहमत हुँ। मैं मॉड्यूल -3 में अपने ऑपरेटिंग सिस्टम लिखूंगा, जो पॉइंटर कोड को नियंत्रित करने और समझने के लिए बेहतर तंत्र प्रदान करता है। लेकिन सूचक कार्यक्रमों को लिखा जाना है, और एचओपीएल -2 में डेनिस रिची के लेख को पढ़ने के बाद, मेरा मानना ​​है कि सी उस जगह को इतनी अच्छी तरह से मानता है कि इसे कभी भी प्रतिस्थापित नहीं किया जाएगा। लेकिन लोगों को इसमें आवेदन लिखना बंद कर देना चाहिए! (और जावा के लिए धन्यवाद, कई ने ऐसा किया है।) –

+0

मुझे लगता है कि सी निहित रूपांतरण कोड को अधिभारित किए बिना समझने के लिए पर्याप्त कठिन बनाते हैं! +1 – SingleNegationElimination

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