मैं ऑपरेटर को ओवरलोडिंग के खिलाफ तर्कों को नहीं समझता [बंद]


82

मैंने अभी जोएल का एक लेख पढ़ा है जिसमें वह कहता है:

सामान्य तौर पर, मुझे यह स्वीकार करना होगा कि मैं भाषा सुविधाओं से थोड़ा डरता हूं जो चीजों को छिपाते हैं । जब आप कोड देखेंगे

i = j * 5;

... सी में आप जानते हैं, कम से कम, कि जे को पांच से गुणा किया जा रहा है और परिणाम I में संग्रहीत हैं।

लेकिन अगर आप C ++ में कोड के समान स्निपेट देखते हैं, तो आपको कुछ भी पता नहीं है। कुछ भी तो नहीं। सी ++ में वास्तव में क्या हो रहा है यह जानने का एकमात्र तरीका यह पता लगाना है कि मैं किस प्रकार और जे हैं, कुछ ऐसा जो पूरी तरह से कहीं और घोषित किया जा सकता है। ऐसा इसलिए है क्योंकि j एक प्रकार का हो सकता है जो operator*अतिभारित हो गया है और जब आप इसे गुणा करने का प्रयास करते हैं तो यह बहुत ही विकट होता है।

(जोर मेरा।) चीजों को छिपाने वाली भाषा सुविधाओं से डरना? आप उससे कैसे डर सकते हैं? ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग के प्रमुख विचारों में से एक को छिपाने ( अमूर्त रूप में भी जाना जाता है ) नहीं है? हर बार जब आप कोई विधि कहते हैं a.foo(b), तो आपके पास कोई विचार नहीं होता कि वह क्या कर सकता है। आपको यह पता लगाना होगा कि क्या प्रकार हैं aऔर क्या bहैं, कुछ ऐसा जो पूरी तरह से कहीं और घोषित किया जा सकता है। तो क्या हमें ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग को दूर करना चाहिए, क्योंकि यह प्रोग्रामर से बहुत अधिक चीजें छिपाता है?

और j * 5किसी भी तरह से अलग कैसे है j.multiply(5), जिसे आपको एक ऐसी भाषा में लिखना पड़ सकता है जो ऑपरेटर ओवरलोडिंग का समर्थन नहीं करता है? फिर, आपको विधि के jअंदर और प्रकार के बारे में पता लगाना होगा multiply, क्योंकि लो और निहारना, jएक प्रकार का हो सकता है जिसमें एक ऐसी multiplyविधि होती है जो बहुत कुछ मजाकिया ढंग से करती है।

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

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

कृपया मुझे ज्ञान दो।


20
+1: अच्छी तरह से लिखा गया है, अच्छी तरह से तर्क दिया गया है, दिलचस्प विषय और अत्यधिक बहस योग्य है। एक p.se प्रश्न का एक चमकदार उदाहरण।
एलोन गुरिलनेक

19
+1: लोग जोएल स्पॉल्स्की को सुनते हैं क्योंकि वह अच्छी तरह से लिखते हैं और प्रसिद्ध हैं। लेकिन वह उसे सही समय का 100% नहीं बनाता है। मैं आपके तर्क से सहमत हूं। अगर हम सभी जोएल के तर्क का अनुसरण करते हैं, तो हम कभी भी कहीं नहीं पहुंचेंगे।
कोई नहीं

5
मेरा तर्क है कि या तो मुझे और जम्मू को स्थानीय रूप से घोषित किया जाता है ताकि आप उनके प्रकार को जल्दी से देख सकें, या वे बेकार चर नाम रख सकें और उनका नाम बदला जाए।
कैमरून मैकफारलैंड

5
+1, लेकिन जोएल के लेख का सबसे अच्छा हिस्सा मत भूलना: सही उत्तर की ओर एक मैराथन दौड़ने के बाद, वह बिना किसी स्पष्ट कारण के 50 फीट कम हो जाता है। गलत कोड सिर्फ गलत नहीं दिखना चाहिए; यह संकलन नहीं होना चाहिए।
लैरी कोलमैन

3
@ लॉरी: आप वर्गों को उचित रूप से परिभाषित करके गलत कोड बनाने में विफल हो सकते हैं, इसलिए उनके उदाहरण में आप C ++ में SafeString और UnsafeString, या RowIndex और ColumnIndex कर सकते हैं, लेकिन आपको उन्हें सहज रूप से व्यवहार करने के लिए ऑपरेटर ओवरलोडिंग का उपयोग करना होगा।
डेविड थॉर्नले

जवाबों:


32

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

मुझे ऐसा कुछ दिखाई नहीं दे रहा है * ऐसा कुछ करें जो Get_Some_Data नामक फ़ंक्शन की तुलना में किसी भी बेहतर तरीके से गुणा न करें जो डेटा को हटा देता है।


13
+1 के लिए 'मैं नहीं देखता' बिट। भाषा सुविधाएँ उपयोग के लिए हैं, दुरुपयोग नहीं।
माइकल के

5
फिर भी हमारे पास <<धाराओं पर परिभाषित एक ऑपरेटर है जिसका बिटवे शिफ्ट से कोई लेना-देना नहीं है, ठीक C ++ के मानक पुस्तकालय में।
मैल्कम

the बिटवाइज़ शिफ्ट ’ऑपरेटर को केवल ऐतिहासिक कारणों से ही बुलाया जाता है। जब मानक प्रकारों पर लागू किया जाता है, तो यह एक बिटवाइज़ शिफ्ट करता है (उसी तरह जिसमें + ऑपरेटर संख्यात्मक प्रकारों पर लागू होने पर एक साथ संख्या जोड़ता है), हालांकि जब एक जटिल प्रकार पर लागू किया जाता है, तो यह वही कर सकता है जो इसे पसंद करता है, जब तक यह बनाता है उस प्रकार के लिए समझ।
gbjbaanb

1
* का उपयोग डेरीफेरिंग के लिए भी किया जाता है (जैसा कि स्मार्ट पॉइंटर्स और पुनरावृत्तियों द्वारा किया जाता है); यह स्पष्ट नहीं है कि अच्छे और बुरे ओवरलोडिंग के बीच सीमा कहां रखी जाए
martinkunev

यह कहीं भी नहीं होगा, यह j की परिभाषा में होगा।
एंडी

19

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

उदाहरण के लिए, यह ओवरलोड सही समझ में आता है +या *के लिए ऑपरेटर class Matrixया class Complex। सभी को तुरंत पता चल जाएगा कि इसका क्या मतलब है। दूसरी ओर, मेरे लिए इस तथ्य का +अर्थ है कि स्ट्रिंग्स का संघटन बिल्कुल स्पष्ट नहीं है, भले ही जावा भाषा के एक हिस्से के रूप में ऐसा करता है, और एसटीएल std::stringऑपरेटर ओवरलोडिंग का उपयोग करने के लिए करता है ।

एक और अच्छा उदाहरण है जब ऑपरेटर ओवरलोडिंग कोड को अधिक स्पष्ट बनाता है C ++ में स्मार्ट पॉइंटर्स। आप चाहते हैं कि स्मार्ट पॉइंटर्स यथासंभव नियमित पॉइंटर्स की तरह व्यवहार करें, इसलिए यह एकात्मक *और ->ऑपरेटरों को अधिभारित करने के लिए सही समझ में आता है ।

संक्षेप में, ऑपरेटर ओवरलोडिंग एक फ़ंक्शन का नाम देने के लिए सिर्फ एक और तरीके से ज्यादा कुछ नहीं है। और नामकरण कार्यों के लिए एक नियम है: नाम वर्णनात्मक होना चाहिए, यह तुरंत स्पष्ट करता है कि फ़ंक्शन क्या करता है। वही सटीक नियम ऑपरेटर ओवरलोडिंग पर लागू होता है।


1
आपके अंतिम दो वाक्य ऑपरेटर के ओवरलोडिंग पर आपत्ति जताने के लिए मिलते हैं: सभी कोड की इच्छा तुरंत स्पष्ट हो।
लैरी कोलमैन

2
क्या यह स्पष्ट नहीं है कि M * N का अर्थ है, जहां M और N टाइप मैट्रिक्स के हैं?
दीमा

2
@ पसंदीदा: नहींं। मैट्रिक्स गुणन का एक प्रकार है। आप एक nxk मैट्रिक्स द्वारा एक mxn मैट्रिक्स को गुणा कर सकते हैं और एक mxk मैट्रिक्स प्राप्त कर सकते हैं।
Dima

1
@FredOverflow: तीन-आयामी वेक्टर को गुणा करने के अलग-अलग तरीके हैं, एक आपको स्केलर देता है और दूसरा आपको एक और तीन-आयामी वेक्टर देता है, और इसलिए *उन पर अधिक भार डालने से भ्रम पैदा हो सकता है। संभवतः आप operator*()डॉट उत्पाद के operator%()लिए और क्रॉस उत्पाद के लिए उपयोग कर सकते हैं , लेकिन मैं एक सामान्य-उपयोग वाली लाइब्रेरी के लिए ऐसा नहीं करूंगा।
डेविड थॉर्नले

2
@ मर्टिन बेकेट: नहीं। सी ++ A-Bको B-Aया तो फिर से चालू करने की अनुमति नहीं है , और सभी ऑपरेटर उस पैटर्न का पालन करते हैं। हालांकि हमेशा एक अपवाद होता है: जब कंपाइलर साबित कर सकता है कि कोई फर्क नहीं पड़ता, तो उसे सब कुछ फिर से व्यवस्थित करने की अनुमति है।
जोएर्ड

9

हास्केल में "+", "-", "*", "/" आदि सिर्फ (इन्फिक्स) फ़ंक्शन हैं।

क्या आपको "4 प्लस 2" के रूप में एक इनफ़िक्स फ़ंक्शन "प्लस" नाम देना चाहिए? क्यों नहीं, अगर इसके अलावा जो आपके कार्य करता है। क्या आपको अपना "प्लस" फ़ंक्शन "+" नाम देना चाहिए? क्यों नहीं।

मुझे लगता है कि तथाकथित "ऑपरेटरों" के साथ मुद्दा यह है कि वे ज्यादातर गणितीय कार्यों से मिलते-जुलते हैं और उन लोगों की व्याख्या करने के कई तरीके नहीं हैं और इस तरह इस तरह की विधि / फ़ंक्शन / ऑपरेटर के बारे में उच्च उम्मीदें हैं।

संपादित करें: मेरी बात को और स्पष्ट किया


एर्म, सी, सी ++ से विरासत में मिला को छोड़कर (और यही फ्रेड के बारे में पूछ रहा था) बहुत ज्यादा एक ही बात करता है। अब आपका क्या लेना देना है यह अच्छा है या बुरा?
sbi

@sbi मैं ऑपरेटर ओवरलोडिंग प्यार ... असल में भी सी अतिभारित है ऑपरेटरों ... आप उनके लिए उपयोग कर सकते हैं int, float, long longऔर जो कुछ भी। तो आखिर ऐसा क्या है?
फ़ूजएक्सल

@FUZxxl: यह उपयोगकर्ता द्वारा परिभाषित ऑपरेटरों के बारे में है जो बिल्ट-इन को ओवरलोड करते हैं।
sbi

1
@sbi हास्केल के बीच कोई फर्क नहीं है builtin और उपयोगकर्ता परिभाषित । सभी ऑपरेटर समान हैं। आप कुछ एक्सटेंशन भी चालू कर सकते हैं जो सभी पूर्वनिर्धारित सामान को हटा दें और आपको किसी भी ऑपरेटर सहित, खरोंच से कुछ भी लिखने दें।
फ़ूजएक्सल

@FUZxxl: यह अच्छी तरह से हो सकता है, लेकिन ओवरलोड ऑपरेटरों का विरोध करने वाले आमतौर पर +अलग-अलग अंतर्निहित संख्याओं के लिए अंतर्निहित उपयोग करने का विरोध नहीं करते हैं, लेकिन उपयोगकर्ता-परिभाषित ओवरलोड का निर्माण करते हैं। इसलिए मेरी टिप्पणी।
भारतीय स्टेट बैंक

7

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

यह दो कारणों से दुखद है:

  1. अपने तार्किक निष्कर्ष पर पहुंचा, यह सिद्धांत कि कोड तुरंत स्पष्ट होना चाहिए हम सभी को अभी भी COBOL में कोडिंग करना होगा।
  2. आप उस कोड से नहीं सीखते जो तुरंत स्पष्ट होता है। आप उस कोड से सीखते हैं जो एक बार समझ में आता है कि आप यह सोचने के लिए कुछ समय लेते हैं कि यह कैसे काम करता है।

कोड से सीखना हमेशा प्राथमिक उद्देश्य नहीं होता है। "फीचर X जैसे मामले में गड़बड़ है, जो व्यक्ति इसे लिखता है उसने कंपनी छोड़ दी है, और आपको इसे ASAP ठीक करने की आवश्यकता है", मेरे पास बहुत कोड है जो तुरंत स्पष्ट है।
इरर्सजेट

5

मैं कुछ हद तक सहमत हूं।

यदि आप लिखते हैं multiply(j,5), jएक अदिश या मैट्रिक्स प्रकार का हो सकता है, जो multiply()कम या ज्यादा जटिल है, जो इस पर निर्भर करता jहै। हालांकि, यदि आप पूरी तरह से ओवरलोडिंग के विचार को छोड़ देते हैं, तो फ़ंक्शन को नाम देना होगा multiply_scalar()या multiply_matrix()जो यह स्पष्ट करेगा कि नीचे क्या हो रहा है।

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


अच्छी बात। हालाँकि, ओवरलोडिंग को पूरी तरह से छोड़ना सामान्य प्रोग्रामिंग के साथ अच्छा नहीं है ...
fredoverflow

@ फ़्रेडो: बिल्कुल नहीं। लेकिन जेनेरिक प्रोग्रामिंग बहुत अलग प्रकार के लिए एक ही एल्गोरिदम का उपयोग करने के बारे में है, इसलिए पसंद करने वाले लोग multiply_matrix()जेनेरिक प्रोग्रामिंग को पसंद नहीं करेंगे।
sbi

2
आप नामों के बारे में आशावादी हैं, आप नहीं हैं? मैंने जिन कुछ स्थानों पर काम किया है, उनके आधार पर, मैं 'मल्टीप्लाई' ('और' मल्टीप्लेम () `या शायद real_multiply()या तो जैसे नामों की उम्मीद करूँगा । डेवलपर्स अक्सर नामों के साथ अच्छे नहीं होते हैं, और operator*()कम से कम सुसंगत होने वाले हैं।
डेविड थॉर्नले

@ डेविड: हाँ, मैं इस तथ्य पर छोड़ दिया कि नाम खराब हो सकते हैं। लेकिन तब हम केवल यह मान operator*()सकते हैं कि कुछ मूर्खतापूर्ण हो सकता है, jएक मैक्रो है जो पांच फ़ंक्शन कॉल और व्हाट्सएप के भावों का मूल्यांकन कर रहा है। आप तब दोनों दृष्टिकोणों की तुलना नहीं कर सकते। लेकिन, हां, चीजों को अच्छी तरह से नाम देना कठिन है, हालांकि जो भी समय लगता है उसके लायक है।
sbi

5
@ डेविड: और चूंकि नामकरण कठिन है, नामों को प्रोग्रामिंग भाषाओं से हटा दिया जाना चाहिए, है ना? यह सिर्फ उन्हें गलत पाने के लिए बहुत आसान है! ;-)
fredoverflow

4

मैं ऑपरेटर ओवरलोडिंग के साथ दो समस्याओं को देखता हूं।

  1. अधिभार ऑपरेटर के शब्दार्थ को बदल देता है, भले ही वह प्रोग्रामर का इरादा न हो। उदाहरण के लिए, जब आप ओवरलोड करते हैं &&, ||या ,, आप उन अनुक्रम बिंदुओं को खो देते हैं जो इन ऑपरेटरों के अंतर्निहित वेरिएंट (साथ ही तार्किक ऑपरेटरों के लघु-परिचालित व्यवहार) द्वारा निहित हैं। इस कारण से, इन ऑपरेटरों को अधिभार नहीं देना बेहतर है, भले ही भाषा इसे अनुमति देती हो।
  2. कुछ लोग ऑपरेटर को इतनी अच्छी सुविधा के रूप में ओवरलोडिंग करते देखते हैं, वे हर जगह इसका उपयोग करना शुरू करते हैं, भले ही यह उचित समाधान न हो। यह अन्य लोगों को दूसरी दिशा में अति-प्रतिक्रिया करने का कारण बनता है और ऑपरेटर ओवरलोडिंग के उपयोग के खिलाफ चेतावनी देता है। मैं किसी भी समूह के साथ सहमत नहीं हूं, लेकिन बीच का रास्ता ले लो: ऑपरेटर ओवरलोडिंग को संयम से और केवल जब इस्तेमाल किया जाना चाहिए
    • अतिभारित ऑपरेटर का डोमेन विशेषज्ञों और सॉफ्टवेयर विशेषज्ञों दोनों के लिए स्वाभाविक अर्थ है। यदि वे दो समूह ऑपरेटर के लिए प्राकृतिक अर्थ पर सहमत नहीं हैं, तो इसे अधिभार न डालें।
    • शामिल प्रकार (ओं) के लिए, ऑपरेटर और तात्कालिक संदर्भ के लिए कोई प्राकृतिक अर्थ नहीं है (अधिमानतः एक ही अभिव्यक्ति, लेकिन कुछ लाइनों से अधिक नहीं) हमेशा यह स्पष्ट करता है कि ऑपरेटर का अर्थ क्या है। इस श्रेणी का एक उदाहरण operator<<धाराओं के लिए होगा ।

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

@FredOverflow "नया और गर्म" जो कुछ भी है, उस पर दूसरा तर्क लागू किया जा सकता है। मैं इसे ऑपरेटर को एक भाषा से ओवरलोडिंग को हटाने के तर्क के रूप में नहीं दे रहा हूं, लेकिन एक कारण के रूप में लोग इसके खिलाफ तर्क देते हैं। जहां तक ​​मेरा सवाल है, ऑपरेटर ओवरलोडिंग उपयोगी है लेकिन इसका इस्तेमाल सावधानी से किया जाना चाहिए।
बार्ट वैन इनगेन शेंउ

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

बेशक, यह लगभग विचित्र नहीं है क्योंकि कॉमा ऑपरेटर को ओवरलोड होने की अनुमति नहीं है। संयोग से, एक अतिभारित-ईश चीज़ जिसे मैंने वास्तव में नहीं देखा है, लेकिन ऐसा करना होगा, जो तंग-बाध्यकारी सदस्य पहुंच का एक साधन होगा, जिससे एक अभिव्यक्ति की अनुमति दी जा सकती है, जैसे foo.bar[3].Xकि एक सदस्य को बेनकाब करने की fooआवश्यकता के बजाय। fooसदस्यता लेने का समर्थन कर सकता है और फिर एक सदस्य को उजागर कर सकता है X। यदि कोई वास्तविक सदस्य पहुंच के माध्यम से मूल्यांकन को बाध्य करना चाहता है, तो कोई लिखेगा ((foo.bar)[3]).X
सुपरकैट

3

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

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

दूसरे शब्दों में, ऑपरेटर अधिभार को रोकना पाठक के लिए एक लाभ है , न कि लेखक , और इसलिए कार्यक्रमों को बनाए रखना आसान बनाता है!


+1, एक चेतावनी के साथ: C ++ आपको अपने आप को लटकाने के लिए पर्याप्त रस्सी देता है। लेकिन अगर मैं C ++ में लिंक की गई सूची को लागू करना चाहता हूं, तो मैं nth तत्व तक पहुंचने के लिए [] का उपयोग करने की क्षमता चाहता हूं। यह डेटा के लिए ऑपरेटरों का उपयोग करने के लिए समझ में आता है जो (गणितीय रूप से बोलते हुए) वे के लिए मान्य हैं।
माइकल के

@ मिचेल, आप list.get(n)वाक्य रचना के साथ नहीं रह सकते हैं ?

@ थोरबजर्न: यह वास्तव में ठीक है, शायद एक खराब उदाहरण है। समय बेहतर हो सकता है - ओवरलोडिंग +, - समय के बजाय समझ में आएगा। एड (दूसरा समय)।
माइकल के

4
@Michael: लिंक की गई सूचियों के बारे में, std::listओवरलोड नहीं करता है operator[](या सूची में अनुक्रमण का कोई अन्य साधन नहीं देता है), क्योंकि ऐसा ऑपरेशन O (n) होगा, और सूची इंटरफ़ेस को ऐसे फ़ंक्शन को उजागर नहीं करना चाहिए यदि आप दक्षता के बारे में परवाह करते हैं। ग्राहकों को अनुक्रमित के साथ लिंक की गई सूचियों पर पुनरावृति करने के लिए प्रलोभन दिया जा सकता है, जिससे ओ (एन) एल्गोरिदम अनावश्यक रूप से ओ (एन ^ 2) हो जाते हैं। आप जावा कोड में बहुत बार देखते हैं, खासकर यदि लोग उस Listइंटरफ़ेस के साथ काम करते हैं जिसका उद्देश्य पूरी तरह से जटिलता को दूर करना है।
फ्रेडओवरफ्लो

5
@ थोर: "लेकिन कुछ निश्चित होने के लिए आपको जांच करनी होगी :)" ... फिर, यह ऑपरेटर ओवरलोडिंग से बंधा नहीं है । यदि आप देखते हैं time.add(anotherTime), तो आपको यह भी जांचना होगा कि क्या लाइब्रेरी प्रोग्रामर ने ऐड ऑपरेशन "सही ढंग से" लागू किया है (जो भी इसका मतलब है)।
फ्रेडओवरफ्लो

3

ओवरलोडिंग a * bऔर कॉलिंग के बीच एक अंतर multiply(a,b)यह है कि बाद के लिए आसानी से पकड़ लिया जा सकता है। तो multiplyसमारोह के लिए विभिन्न प्रकार के ओवरलोड न हो जाए तो आप पता लगा सकते हैं कि वास्तव में क्या समारोह करने जा रहा है के प्रकार के माध्यम से ट्रैक करने के लिए बिना, aऔर b

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


क्या शुद्ध C में लिनक्स कर्नेल विकसित नहीं हुआ है? इस संदर्भ में चर्चा (ऑपरेटर) ओवरलोडिंग क्यों?
फ्रेडओवरफ्लो

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

@FredOverflow: लिनक्स कर्नेल वास्तव में GCC C में है। यह सभी प्रकार के एक्सटेंशन का उपयोग करता है जो कुछ समय में अपने C को लगभग C ++ का अनुभव देते हैं। मैं कुछ फैंसी प्रकार के जोड़तोड़ के बारे में सोच रहा हूं।
ज़ैन लिंक्स

2
@ बहिष्कार: सी में प्रोग्राम की गई परियोजनाओं के संबंध में ओवरलोडिंग की "बुराई" पर चर्चा करने का कोई मतलब नहीं है, क्योंकि सी में कार्यों को अधिभार करने की क्षमता नहीं है।
फ्रेडओवरफ्लो

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

2

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

व्यक्तिगत रूप से मुझे लगता है कि एक अंतर है। जब आप भाषा के अंतर्निहित वाक्यविन्यास के व्यवहार को बदल सकते हैं, तो यह तर्क करने के लिए अधिक अपारदर्शी हो जाता है। मेटा-प्रोग्रामिंग की अनुमति नहीं देने वाली भाषाएँ वाक्य-रचना में कम शक्तिशाली होती हैं, लेकिन समझने के लिए वैचारिक रूप से सरल होती हैं।


ओवरलोड ऑपरेटरों को कभी भी "कुछ अजीब" नहीं करना चाहिए। यह ठीक है अगर यह कुछ जटिल करता है, तो निश्चित रूप से। लेकिन केवल ओवरलोड होने पर इसका एक, स्पष्ट अर्थ होता है।
सोजेरड

2

मुझे लगता है कि सी ++ में ऑपरेटर ओवरलोडिंग के साथ ओवरलोडिंग गणित ऑपरेटरों असली मुद्दा नहीं है। मुझे लगता है कि ओवरलोडिंग ऑपरेटरों को अभिव्यक्ति के संदर्भ पर भरोसा नहीं करना चाहिए (अर्थात प्रकार) "बुराई" है। जैसे ओवरलोडिंग , [ ] ( ) -> ->* new deleteया यहां तक ​​कि एकात्मक *। आपके पास उन ऑपरेटरों से उम्मीदों का एक निश्चित सेट है जिन्हें कभी नहीं बदलना चाहिए।


+1 न करें [] ++ के बराबर।
माइकल के

3
आप कह रहे हैं हम ऑपरेटरों आप का उल्लेख ओवरलोड सक्षम नहीं होना चाहिए सब पर ? या आप सिर्फ यह कह रहे हैं कि हमें उन्हें केवल उद्देश्यों के लिए अधिभार देना चाहिए? क्योंकि मैं कंटेनरों को बिना देखे operator[], बिना फंक्शंस के operator(), स्मार्ट पॉइंटर्स के बिना operator->और इतने पर देखना पसंद करूंगा ।
फ्रेडओवरफ्लो

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

2

मैं पूरी तरह से समझता हूं कि आपको छिपने के बारे में जोएल का तर्क पसंद नहीं है। न ही मैं। बिल्ट-इन न्यूमेरिकल टाइप जैसी चीजों के लिए या अपने जैसे, जैसे, मैट्रिक्स के लिए '+' का उपयोग करना वास्तव में बहुत बेहतर है। मैं मानता हूँ कि यह '.multiply ()' के बजाय '*' के साथ दो मैट्रिसेस को गुणा करने में सक्षम होने के लिए साफ-सुथरा और सुरुचिपूर्ण है। और आखिरकार हम दोनों ही मामलों में एक ही तरह के अमूर्त हैं।

यहाँ क्या दर्द होता है यह आपके कोड की पठनीयता है। वास्तविक जीवन के मामलों में, मैट्रिक्स गुणा के शैक्षणिक उदाहरण में नहीं। खासकर अगर आपकी भाषा उन ऑपरेटरों को परिभाषित करने की अनुमति देती है जो शुरू में भाषा कोर में मौजूद नहीं हैं, उदाहरण के लिए =:=। इस बिंदु पर बहुत सारे अतिरिक्त प्रश्न उठते हैं। उस शापित ऑपरेटर के बारे में क्या है? मेरा मतलब है कि उस चीज़ की पूर्वता क्या है? संघवाद क्या है? a =:= b =:= cवास्तव में किस क्रम में निष्पादित किया जाता है?

यह पहले से ही ऑपरेटर ओवरलोडिंग के खिलाफ एक तर्क है। अभी भी यकीन नहीं हुआ? पूर्वता के नियमों की जाँच करने पर आपको 10 सेकंड नहीं लगे? ठीक है, आगे चलते हैं।

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

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


1
मौजूदा ऑपरेटरों को ओवरलोड करना और नए ऑपरेटरों का आविष्कार करना एक ही बात नहीं है, लेकिन मेरे से +1 है।
fredoverflow

1

सामान्य तौर पर, मैं गैर-सहज तरीके से ऑपरेटर ओवरलोडिंग का उपयोग करने से बचता हूं। यही है, अगर मेरे पास एक संख्यात्मक वर्ग है, तो ओवरलोडिंग * स्वीकार्य (और प्रोत्साहित) है। हालांकि, अगर मेरे पास एक कर्मचारी वर्ग है, तो ओवरलोडिंग * क्या करेगा? दूसरे शब्दों में, सहज ज्ञान युक्त तरीकों से ओवरलोड ऑपरेटरों को पढ़ने और समझने में आसानी होती है।

स्वीकार्य / उत्साहित:

class Complex
{
public:
    double r;
    double i;

    Complex operator*(const Compex& rhs)
    {
        Complex result;
        result.r = (r * rhs.r) - (i * rhs.i);
        result.i = (r * rhs.i) + (i * rhs.r);
        return result;
    }
};

स्वीकार्य नहीं है:

class Employee
{
public:
    std::string name;
    std::string address;
    std::string phone_number;

    Employee operator* (const Employee& e)
    {
        // what the hell do I do here??
    }
};

1
कर्मचारियों को गुणा करना? निश्चित रूप से यह एक अपमानजनक अपराध है, अगर वे बोर्डरूम की मेज पर करते हैं, तो यह है।
gbjbaanb

1

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

C ++ अपने आप में इस तरह के मामले का एक शानदार उदाहरण प्रदान करता है। कैसे stream << 1पढ़ा जाए? धारा 1 के द्वारा छोड़ी गई है? यह बिल्कुल भी स्पष्ट नहीं है जब तक आप स्पष्ट रूप से नहीं जानते कि << C ++ में भी स्ट्रीम को लिखते हैं। हालाँकि, अगर यह ऑपरेशन एक विधि के रूप में लागू किया गया था, तो कोई भी डेवलपर डेवलपर नहीं लिखेगा o.leftShift(1), यह कुछ इस तरह होगा o.write(1)

लब्बोलुआब यह है कि ऑपरेटर को ओवरलोडिंग से अनुपलब्ध बनाकर, भाषा प्रोग्रामर को संचालन के नामों के बारे में सोचती है। यहां तक ​​कि अगर चुना हुआ नाम सही नहीं है, तब भी किसी नाम की गलत व्याख्या करना मुश्किल है।


1

वर्तनी के तरीकों की तुलना में, ऑपरेटर कम होते हैं, लेकिन उन्हें कोष्ठक की भी आवश्यकता नहीं होती है। कोष्ठक टाइप करने के लिए अपेक्षाकृत असुविधाजनक हैं। और आपको उन्हें संतुलित करना होगा। कुल मिलाकर, किसी भी विधि कॉल के लिए ऑपरेटर की तुलना में सादे शोर के तीन वर्णों की आवश्यकता होती है। यह ऑपरेटरों को बहुत, बहुत लुभावना बनाने का उपयोग करता है।
कोई और ऐसा क्यों चाहेगा cout << "Hello world":?

ओवरलोडिंग के साथ समस्या यह है कि अधिकांश प्रोग्रामर अविश्वसनीय रूप से आलसी हैं और अधिकांश प्रोग्रामर होने का जोखिम नहीं उठा सकते हैं।

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


या, किसी प्रतिनिधि को एक घटना टाई करने के लिए + = का उपयोग करने के लिए सी # में। मुझे नहीं लगता कि प्रोग्रामर मूर्खता के लिए भाषा सुविधाओं को दोष देना एक रचनात्मक तरीका है।
gbjbaanb

0

ऑपरेटर ओवरलोडिंग का कारण डरावना है, क्योंकि बड़ी संख्या में प्रोग्रामर हैं जो कभी भी *ऐसा नहीं सोचते हैं कि इसका मतलब यह नहीं है कि केवल "गुणा" करें, जबकि foo.multiply(bar)कम से कम तुरन्त जैसे एक तरीका उस प्रोग्रामर को इंगित करता है कि किसी ने एक कस्टम गुणा पद्धति लिखी है । किस बिंदु पर वे आश्चर्यचकित होंगे कि जांच क्यों और कैसे हुई।

मैंने "अच्छे प्रोग्रामर" के साथ काम किया है जो उच्च स्तर के पदों पर थे जो "तुलनाविलास" नामक विधियाँ बनाते थे जो 2 तर्क लेते थे, और एक से दूसरे में मूल्यों को लागू करते थे और एक बूलियन वापस करते थे। या "LoadTheValues" नामक एक विधि जो 3 अन्य वस्तुओं के लिए डेटाबेस में जाएगी, मान प्राप्त करें, गणना करें, thisइसे संशोधित करें और इसे डेटाबेस में सहेजें।

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

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.