2009-07-22 13 views
33

मुझे सामान्यीकरण बनाम बहुरूपता के संबंध में निर्णय लेना है।सी ++ मानक अभ्यास: वर्चुअल इंटरफ़ेस कक्षा बनाम टेम्पलेट्स

अच्छी तरह से परिदृश्य मानक है: मैं अपने मोनोलिथिक परस्पर निर्भर कोड को अधिक मॉड्यूलर, स्वच्छ और एक्स्टेंसिबल बनाना चाहता हूं। यह अभी भी एक मंच में है जहां डिजाइन सिद्धांत में परिवर्तन करने योग्य है, और, जैसा कि मैंने इसे देखा, अत्यधिक वांछनीय।

क्या मैं पूरी तरह वर्चुअल बेस क्लासेस (इंटरफेस) या टेम्पलेट्स पेश करूंगा?

मैं टेम्पलेट विकल्प के बारे में मूल बातें के बारे में पता कर रहा हूँ: कम अविवेक, बेहतर प्रदर्शन, अधिक लेकिन कोई लेट बाइंडिंग, और इतने पर संकलन।

एसटीएल ज्यादा (या कोई नहीं?) विरासत का उपयोग नहीं करता है, और बढ़ावा भी नहीं होता है। लेकिन मुझे लगता है कि उन लोगों को वास्तव में छोटे मूल उपकरण होने का लक्ष्य है जिनका उपयोग प्रोग्रामर द्वारा कोड की प्रत्येक पंक्ति के 2 लाइनों का उपयोग किया जाता है।

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

खैर मेरा परिदृश्य कुछ हद तक भीतर है।

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

इससे मुझे कुछ हद तक टेम्पलेट समाधान की सुविधा मिलती है। मेरे लिए यह कुछ हद तक क्लीनर भी दिखता है।

क्या कोई बड़ा बुरा प्रभाव है, क्या इंटरफेस अभी भी जाने के लिए हैं? वे कब नहीं हैं जो मानक सी ++ शैली के साथ अधिक अनुपालन करता है?

मुझे पता है कि यह व्यक्तिपरक पर सीमा है, लेकिन मुझे वास्तव में कुछ अनुभवों में दिलचस्पी है। मैं स्कॉट Meyers प्रभावी सी की एक प्रति के स्वामी नहीं हैं ++ इसलिए मैं अपने उम्मीदें तुम लोग :)

उत्तर

20

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

टेम्पलेट्स के लिए एकमात्र संभावित डाउनसाइड्स यह है कि 1) उन्हें आम तौर पर शीर्षकों में परिभाषित किया जाना चाहिए (जिसका अर्थ है कि अधिक कोड # समाहित हो जाता है), और यह अक्सर धीमी संकलन-समय की ओर जाता है।

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

जो मानक सी ++ शैली के साथ अधिक अनुपालन करता है?

"मानक सी ++ शैली" क्या है, इस पर निर्भर करता है। सी ++ मानक पुस्तकालय सब कुछ का उपयोग करता है।एसटीएल सबकुछ के लिए टेम्पलेट का उपयोग करता है, थोड़ी पुरानी आईओएसट्रीम लाइब्रेरी विरासत और आभासी कार्यों का उपयोग करती है, और सी से प्राप्त लाइब्रेरी फ़ंक्शंस न तो, बिल्कुल उपयोग करता है।

इन दिनों, टेम्पलेट्स अब तक के सबसे लोकप्रिय विकल्प हैं, और मुझे कहना होगा कि यह सबसे "मानक" दृष्टिकोण है।

+3

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

+3

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

8

यह एक झूठा विरोध है। हां, विरासत और आभासी कार्यों का प्रमुख उपयोग iostreams में है, जो बहुत पुराने हैं, और std पुस्तकालयों के बाकी हिस्सों में काफी अलग शैली में लिखे गए हैं।

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

boost::any और std::tr1::function (पूर्व में भी बढ़ावा से) अच्छे उदाहरण हैं।

वे दोनों आइटम के कंटेनर हैं जो संकलित समय पर अज्ञात प्रकार अज्ञात हैं (यह विशेष रूप से any के साथ स्पष्ट है, क्योंकि इसका मूल्य प्राप्त करने के लिए गतिशील कास्ट ऑपरेटर है)।

+0

+1 आपका उत्तर बहुत प्रबुद्ध था, लेकिन सवाल के अनुपालन में मैंने आधा सलाह स्वीकार की। धन्यवाद। – AndreasT

9

क्लासिक वस्तु उन्मुख बहुरूपता के गुण:

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

गुण टेम्पलेट से लग रहे हैं:

  • संकलन समय बाध्यकारी और अधिक आक्रामक optimizat की अनुमति देता है आयनों, लेकिन रन-टाइम लचीलापन
  • डक-टाइपिंग अधिक अजीब लग सकता है, लेकिन असफलता आमतौर पर संकलित-समय विफलताओं
  • कभी-कभी पढ़ने और समझने में कठिन हो सकती है; अवधारणाओं के बिना, संकलक निदान कभी-कभी

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

+0

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

+2

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

0

मेरे दृष्टिकोण से यह वही है जो आप सबसे अच्छे हैं। यदि आप ओओ का उपयोग ओओ के साथ अधिक अनुभव है। यदि आपके पास जेनेरिक जेनिक्स का उपयोग करने के साथ अधिक अनुभव है।

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

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

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

4

अपनी थाली पर एक छोटे से अधिक अनुभव shoveled होने के बाद, वहाँ टेम्पलेट्स में कुछ चीजें हैं जो मुझे पसंद नहीं है कर रहे हैं: वहाँ कुछ नुकसान है कि एक उपयोगी भाषा होने से टेम्पलेट मेटा प्रोग्रामिंग को अयोग्य घोषित कर रहे हैं:

  • पठनीयता: बहुत से कोष्ठक, कई ग़ैर भाषा से लागू (इसलिए दुरुपयोग) सम्मेलनों
  • किसी प्रोग्रामिंग भाषाओं में हमेशा की तरह विकास के दौर से गुजर के लिए, टेम्पलेट्स हैं अपठनीय und समझ से बाहर (बस बढ़ावा BGL के देखो)
  • कभी कभी यह किसी की कोशिश की तरह लगता है डब्ल्यू के लिए अजीब में एक सी ++ कोड जेनरेटर rite।
  • कंपाइलर त्रुटि संदेश सीएल (पूर्ण) एड क्रैप
  • कार्यक्षमता जैसी कुछ बुनियादी "भाषा" प्राप्त करने के लिए बहुत से हैक आवश्यक हैं (उनमें से अधिकतर सी ++ 0x में उपचार किए गए हैं)।
  • कार्यान्वयन फ़ाइलों में कोई टेम्पलेट नतीजा केवल लाइब्रेरी (जो एक बहुत ही दो तरफा तलवार है)
  • सामान्य आईडीई कोड समापन सुविधाओं टेम्पलेट्स के साथ बहुत मदद नहीं कर रहे हैं।
  • एमपीएल में बड़ी चीजें करना "haggly" लगता है, इसके लिए एक और शब्द नहीं मिल रहा है। टेम्पलेट कोड की प्रत्येक पंक्ति उस टेम्पलेट प्रकार पर बाधा उत्पन्न करती है, जो पाठ-प्रतिस्थापन के तरीके में लागू होती है। विरासत पदानुक्रमों में निहित अर्थशास्त्र हैं, टेम्पलेट संरचनाओं में कोई भी नहीं है। ऐसा लगता है कि सबकुछ एक शून्य है * और संकलक आपको बताता है कि क्या सीगफॉल्ट होगा।

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

0

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

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