2012-03-07 10 views
12

मैंने अभी सीखा है कि std :: फ़ंक्शन वास्तव में किस बारे में है और इसके लिए क्या उपयोग किया जाता है और मेरे पास एक प्रश्न है: अब जब हमारे पास अनिवार्य रूप से प्रतिनिधि हैं, तो हमें सार बेस क्लासेस का उपयोग कब और कब करना चाहिए और इसके बजाय, हम एक सामान्य वर्ग में खिलाया std :: समारोह वस्तुओं के माध्यम से polymorphism लागू करना चाहिए? क्या एबीसी को सी ++ 11 में घातक झटका लगा?क्या मुझे अमूर्त बेस क्लासेस/इंटरफेस का उपयोग करना बंद कर देना चाहिए और इसके बजाय boost :: function/std :: function का उपयोग करना चाहिए?

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

+2

'std :: function' फ़ंक्शन-पॉइंटर्स से अलग कैसे है (* इस संदर्भ में * कौन सा)? मुझे कोई मतभेद नज़र नहीं आ रहा है। यदि ऐसा है, तो सी ++ 11 के साथ क्या करना है? आप प्री-सी ++ 11 में रनटाइम पॉलीमोर्फिज्म को लागू करने के लिए फ़ंक्शन-पॉइंटर्स का भी उपयोग कर सकते हैं। – Nawaz

+0

मुझे यह भी सुनिश्चित नहीं है कि उत्तर कैसे देना शुरू करें ... उदाहरण के लिए std :: फ़ंक्शन में विभिन्न प्रकार और तर्कों की संख्या के साथ फ़ंक्शंस में पॉइंटर हो सकता है क्योंकि आप वास्तव में इसे पार करने से पहले std :: bind कर सकते हैं। और, जाहिर है, यह उपयोग करने के लिए आसान तरीका है। यदि कुछ भी आप पूछ सकते हैं कि यह क्या कर सकता है _functors_ क्या नहीं कर सकता ... यह प्रश्न मैं समझूंगा। फिर भी, प्रतिनिधियों को बनाने के लिए मानक और * सरल * तरीके के अलावा, मेरे प्रश्न को वैसे भी उत्पन्न हुआ है। – Zeks

+0

"* फिर भी, प्रतिनिधियों को बनाने के लिए मानक और सरल तरीके के अलावा, मेरे प्रश्न को वैसे भी उत्पन्न किया गया है। *" ... लेकिन यह सार आधार और वर्चुअल फ़ंक्शंस का उपयोग करने से * सरल नहीं है, तो बिंदु क्या है? – Nawaz

उत्तर

19

अच्छी तरह से कॉलबैक

साथ std::function (पहले boost::function) समस्या खत्म हो इंटरफेस परिभाषित पसंद करते हैं समय की सबसे आप एक वर्ग विधि के लिए एक कॉलबैक करने की जरूरत है, और इसलिए समारोह वस्तु को this बाध्य करने के लिए की जरूरत है। हालांकि कॉलिंग कोड में, आपके पास यह जानने का कोई तरीका नहीं है कि this अभी भी आसपास है या नहीं। वास्तव में, आपको कोई जानकारी नहीं है कि this भी है क्योंकि बाइंडर ने कॉलर की आवश्यकता के अनुसार कॉलिंग फ़ंक्शन के हस्ताक्षर को ढाला है।

यह स्वाभाविक रूप से अजीब दुर्घटनाओं का कारण बन सकता है क्योंकि कॉलबैक उन वर्गों के लिए विधियों में आग लगाने का प्रयास करता है जो अब मौजूद नहीं हैं।

आप निश्चित रूप से shared_from_this का उपयोग कर सकते हैं और एक कॉलबैक में shared_ptr को बांध सकते हैं, लेकिन फिर आपका उदाहरण कभी नहीं जा सकता है। जिस व्यक्ति के पास आपको कॉलबैक है, उसके बिना अब भी आपके स्वामित्व में भाग लेता है। आप शायद अधिक अनुमानित स्वामित्व और विनाश चाहते हैं।

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

std::function के साथ एक अतिरिक्त समस्या यह है कि कई डिबगर्स उन्हें अच्छी तरह से समर्थन नहीं करते हैं। वीएस 2008 और बूस्ट फ़ंक्शंस में, आपको अपने फ़ंक्शन पर जाने के लिए लगभग 7 परतों को चरणबद्ध करना होगा। यहां तक ​​कि अगर अन्य सभी चीजें कॉलबैक के बराबर होती हैं तो सबसे अच्छी पसंद थी, std::function के लक्ष्य पर गलती से कदम उठाने की तीव्र परेशानी और समय बर्बाद हो गया था, इससे बचने के लिए पर्याप्त कारण है। विरासत भाषा की मुख्य विशेषता है, और एक इंटरफ़ेस की ओवरराइड विधि में कदम उठाना तात्कालिक है।

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

+0

Thx, "यह" के बारे में बिंदु महत्वपूर्ण है, मैंने इसे नहीं माना है। मैं इसे ध्यान में रखूंगा। – Zeks

+0

@Zeks yup। मैं 'बूस्ट :: फंक्शन' खुश था लेकिन फिर मैंने बाद में खेद व्यक्त किया। इसकी एक विशेषता है जिसमें विशिष्ट उपयोग हैं लेकिन आईएमओ समस्याओं का डिफ़ॉल्ट जवाब नहीं होना चाहिए। –

+0

बीटीडब्ल्यू, क्या std/boost :: function का उपयोग करते समय संभावित नुकसान के बारे में कोई लेख है? "इस" के बारे में चिंता करने की तुलना में इसके लिए और कुछ है? – Zeks

1

मुझे नहीं लगता कि कोई इस निष्कर्ष पर कैसे आ सकता है कि फ़ंक्शन पॉइंटर्स अमूर्त आधार कक्षाओं को अप्रचलित बनाते हैं।

एक वर्ग, उससे संबंधित विधियों और डेटा को समाहित करता है।

एक फ़ंक्शन पॉइंटर, एक फ़ंक्शन पॉइंटर है। इसमें एक encapsulating वस्तु की कोई धारणा नहीं है, यह केवल इसे पारित पैरामीटर के बारे में जानता है।

जब हम कक्षाएं लिखते हैं, तो हम अच्छी तरह परिभाषित वस्तुओं का वर्णन कर रहे हैं।

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

कृपया दोनों को भ्रमित न करें।

+0

मैं नहीं कह रहा हूं कि वे अप्रचलित हैं। बस कुछ std :: समारोह कुछ हद तक समान काम करने के लिए लागू किया जा सकता है। मैं यह पूछ रहा हूँ _because_ मुझे यकीन नहीं है कि दोनों के बीच सीमाएं कहां हैं :) – Zeks

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