दिलचस्प पोस्ट
एक 1 डी संकीर्ण सरणी में नमी के साथ स्थानीय अधिकतम / न्यूनतम खोजना मैं किसी विशिष्ट प्रतिबद्ध के लिए एक github रिपॉजिटरी रोलबैक कैसे कर सकता हूं? IOS 5 में UITabBarItem में पाठ का रंग कैसे बदल सकता है मैं Nokogiri के साथ एक HTML तालिका कैसे पार्स है? अनाम प्रकार का चयन करने के लिए LINQ अभिव्यक्ति ट्री कैसे बनाएं रूबी में एक JSON स्ट्रिंग पार्सिंग NoClassDefFoundError Google Play सेवाओं V2 लाइब्रेरी पर जावास्क्रिप्ट में ट्रिम स्ट्रिंग? अजगर: urllib2 कैसे urlopen अनुरोध के साथ कुकी भेजने के लिए अपलोड किए गए फ़ाइल को JSF में कैसे सहेजें एक दृश्य नियंत्रक को दूसरे दृश्य नियंत्रक में एक सबव्यू के रूप में जोड़ना स्कैला में जेसनॉन लाइब्रेरी का उपयोग कैसे करें? Google मानचित्र पर पारदर्शी गोल कोनों यूनिकोडएनकोड त्रुटि: 'charmap' कोडेक सांकेतिक शब्दों में बदलना नहीं कर सकते हैं – वर्णों को <undefined> के लिए प्रिंट, प्रिंट फ़ंक्शन एक्लिप्स में एक बहु-लाइन जावा स्ट्रिंग चिपकाएं

क्या सी ++ एसटीएल कंटेनर से निकलने का कोई वास्तविक जोखिम है?

दावा है कि यह मानक क्लास के रूप में एक मानक सी + कंटेनर का उपयोग करने के लिए कभी गलती नहीं है, मुझे आश्चर्य होता है

यदि यह घोषित करने के लिए भाषा का दुरुपयोग नहीं है …

// Example A typedef std::vector<double> Rates; typedef std::vector<double> Charges; 

… तो घोषित करने में जोखिम क्या है, वास्तव में …

 // Example B class Rates : public std::vector<double> { // ... } ; class Charges: public std::vector<double> { // ... } ; 

बी में सकारात्मक लाभ शामिल हैं:

  • कार्यों के ओवरलोडिंग को सक्षम करता है क्योंकि एफ (दरें &) और एफ (शुल्क और) अलग हस्ताक्षर हैं I
  • विशिष्ट होने के लिए अन्य टेम्प्लेट को सक्षम करता है, क्योंकि एक्स <दरें> और एक्स <प्रभार> विशिष्ट प्रकार हैं
  • आगे की घोषणा तुच्छ है
  • डिबगर शायद आपको बताता है कि ऑब्जेक्ट एक दरें या शुल्क है या नहीं
  • यदि समय बीतता है, तो दरें और शुल्क व्यक्तियों को विकसित करते हैं – दर के लिए सिंगलटन, प्रभारों के लिए एक आउटपुट प्रारूप – उस कार्यान्वयन के कार्यान्वयन के लिए एक स्पष्ट संभावना है

ए को सकारात्मक लाभ शामिल हैं:

  • कंसल्टर्स आदि के तुच्छ औजारों को उपलब्ध कराने की आवश्यकता नहीं है
  • पन्द्रह वर्षीय पूर्व-मानक संकलक जो केवल एक चीज है जो आपकी विरासत को संकलित करेगा, वह गड़बड़ी नहीं करता है
  • चूंकि विशेषज्ञताओं को असंभव है, टेम्पलेट एक्स <दरें> और टेम्पलेट एक्स <प्रभार> उसी कोड का उपयोग करेंगे, इसलिए कोई बेकार ब्लोट नहीं है

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

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

संपादित करें:

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

संपादित करें:

इस उपयोग के मामले पर गौर करें:

 #include <vector> #include <iostream> void kill_it(std::vector<double> *victim) { // user code, knows nothing of Rates or Charges // invokes non-virtual ~std::vector<double>(), then frees the // memory allocated at address victim delete victim ; } typedef std::vector<double> Rates; class Charges: public std::vector<double> { }; int main(int, char **) { std::vector<double> *p1, *p2; p1 = new Rates; p2 = new Charges; // ??? kill_it(p2); kill_it(p1); return 0; } 

क्या कोई भी संभव त्रुटि है कि यहां तक ​​कि एक मनमाने ढंग से असभ्य उपयोगकर्ता भी इसमें शामिल हो सकता है ??? अनुभाग जो प्रभार (व्युत्पन्न वर्ग) के साथ एक समस्या का परिणाम देगा, लेकिन दरें (टाइपिप्पीफ़) के साथ नहीं?

माइक्रोसॉफ्ट के कार्यान्वयन में, वेक्टर <टी> स्वयं विरासत के माध्यम से कार्यान्वित किया जाता है। सदिश <टी, ए> सार्वजनिक रूप से _Vector_Val <T, A> से व्युत्पन्न है क्या रोकथाम पसंदीदा होना चाहिए?

वेब के समाधान से एकत्रित समाधान "क्या सी ++ एसटीएल कंटेनर से निकलने का कोई वास्तविक जोखिम है?"

मानक कंटेनर के पास वर्चुअल डिस्ट्रक्टर्स नहीं हैं, इस प्रकार आप उन्हें पॉलीमॉर्फिक रूप से संभालना नहीं कर सकते यदि आप नहीं करेंगे, और जो कोई आपके कोड का उपयोग करता है, यह "गलत" नहीं है, प्रति से हालांकि, स्पष्ट रूप से स्पष्ट रूप से संरचना के उपयोग से आप बेहतर हैं।

क्योंकि आपको एक वर्चुअल डिस्ट्रक्टर की जरूरत है और एसटीडी कंटेनर के पास नहीं है। एसटीडी कंटेनर बेस क्लास के रूप में कार्य करने के लिए तैयार नहीं हैं।

अधिक जानकारी के लिए लेख "हम एसटीएल कक्षाओं से एक वर्ग को क्यों नहीं प्राप्त करना चाहिए?"

दिशानिर्देश

आधार वर्ग के पास होना चाहिए:

  • एक सार्वजनिक आभासी नाशक
  • या एक संरक्षित गैर-वर्चुअल डिस्ट्रक्टर

एक मजबूत तर्क-तर्क, मेरी राय में, कि आप अपने प्रकारों पर इंटरफ़ेस और क्रियान्वयन को लागू कर रहे हैं। क्या होता है जब आपको लगता है कि वेक्टर स्मृति आवंटन की रणनीति आपकी आवश्यकताओं के अनुरूप नहीं है? क्या आप std:deque से प्राप्त करेंगे? उन 128 के लाइन कोड के बारे में जो पहले से ही आपके वर्ग का उपयोग करते हैं? क्या सबको हर चीज को पुनः कंपाइल करने की आवश्यकता है? क्या यह भी संकलन करेगा?

यह मुद्दा फिलिज़ोफिकल नहीं है, यह एक कार्यान्वयन मुद्दा है। मानक कंटेनर के डिस्ट्रक्टर्स आभासी नहीं हैं, जिसका अर्थ है कि उचित डिस्क्टस्ट्रक्टर प्राप्त करने के लिए उन पर रनटाइम पॉलिमोरफिसिम का उपयोग करने का कोई तरीका नहीं है।

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

तथ्य के अलावा कि बेस क्लास को वर्चुअल डिस्ट्रक्टर या संरक्षित गैर-वर्चुअल डिस्ट्रिक्टर की जरूरत है, आप अपने डिज़ाइन में निम्न अभिप्राय बना रहे हैं:

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

बिंदु यह है कि एक वर्ग एक तत्व है, जो बहुत से सी ++ में है, जो डिजाइन इरादों को व्यक्त करता है। कहने का मतलब है कि आप क्या कह रहे हैं और आप क्या कह रहे हैं इस तरह से विरासत का उपयोग करने के लिए कारण है

… या मेरी प्रतिक्रिया से पहले ही अधिक संक्षेप में पोस्ट किया: प्रतिस्थापन

इसके अलावा, अधिकतर मामलों में, यदि संभव हो तो आपको विरासत पर संरचना या एकत्रीकरण को प्राथमिकता देना चाहिए।

एक शब्द: उपनिवेश क्षमता

क्या कोई भी संभव त्रुटि है कि यहां तक ​​कि एक मनमाने ढंग से असभ्य उपयोगकर्ता भी इसमें शामिल हो सकता है ??? अनुभाग जो प्रभार (व्युत्पन्न वर्ग) के साथ एक समस्या का परिणाम देगा, लेकिन दरें (टाइपिप्पीफ़) के साथ नहीं?

सबसे पहले, वहाँ मांकरस के उत्कृष्ट बिंदु है:

kill_it में टिप्पणी गलत है यदि गतिशील प्रकार का शिकार std::vector , तो delete केवल अपरिभाषित व्यवहार को आह्वान करता है। kill_it(p2) को कॉल होने के कारण ऐसा होता है, और कुछ भी करने के लिए //??? जोड़ा जाना जरूरी नहीं है। इसके लिए खंड अपरिभाषित व्यवहार है – मानकरसे 3 सितंबर '11 बजे 10:53

दूसरे, कहते हैं कि वे f(*p1); जहां f std::vector<double> विशिष्ट है: उस vector विशेषज्ञता नहीं मिलेगी – आप टेम्प्लेट स्पेशलाइजेशन को अलग तरह से मेल कर सकते हैं – आमतौर पर चल रहे (धीमी या अन्यथा कम कुशल) सामान्य कोड, या एक लिंकर त्रुटि प्राप्त करने पर एक गैर-विशिष्ट संस्करण वास्तव में परिभाषित नहीं है अक्सर एक महत्वपूर्ण चिंता का विषय नहीं

निजी तौर पर, मैं एक पॉइंटर के माध्यम से लाइन को पार करने के आधार पर विनाश का विचार करता हूं – यह केवल आपके "वर्तमान" संकलक, संकलक झंडे, प्रोग्राम, ओएस संस्करण आदि को "काल्पनिक" समस्या (जहाँ तक आप बता सकता है) हो सकता है – लेकिन यह कोई भी "अच्छा" कारण के लिए किसी भी समय तोड़ सकता है

अगर आपको विश्वास है कि आप आधार-श्रेणी के संकेतक के माध्यम से विलोपन से बच सकते हैं, तो इसके लिए जाएं

उसने कहा, आपके मूल्यांकन पर कुछ नोट्स:

  • "कन्स्ट्रक्टरों के मामूली कार्यान्वयन प्रदान करना" – यह एक परेशानी है, लेकिन सी ++ 03 के लिए एक टिप: template <typename A> Classname(const A& a) : Base(a) { } template <typename A, typename B> Classname(const A& a, const B& b) : Base(a, b) { } ... कभी-कभी सभी ओवरलोडों को एन्यूमरेट करने से आसान हो सकता है, लेकिन गैर- const पैरामीटर्स, डिफॉल्ट वैल्यू, स्पष्ट-बनाम-गैर-स्पष्ट कन्स्ट्रक्टर , और बड़े पैमाने पर बहस के पैमाने पर नहीं। सी ++ 11 एक बेहतर सामान्य समाधान प्रदान करता है

बिना प्रश्न के, class Rates या class Charges लिए एक डिस्ट्रक्टर जोड़ना एक जोखिम होगा, क्योंकि std::vector इसके डिस्ट्रक्टर को वर्चुअल के रूप में घोषित नहीं करता है। उदाहरण में कोई नाशक नहीं है, और एक के लिए कोई ज़रूरत नहीं है। दरें या शुल्क नष्ट करने वाले ऑब्जेक्ट को बेस क्लास डिस्ट्रक्टर का इस्तेमाल करना होगा। यहां बहुरूपता की कोई आवश्यकता नहीं है, या तो कोई भी।

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

  • कह रही है "बेस क्लास डिस्ट्रक्टर का आह्वान करेगा" यह ऐसा ध्वनि करता है जैसे कोई अंतर्निहित-परिभाषित व्युत्पन्न श्रेणी के नाशक के साथ सीधे किया जाता है या कॉल करने से – सभी अनुकूलन विवरण और मानक द्वारा निर्दिष्ट नहीं।