2012-03-28 17 views
18

मैं समझता हूं कि गतिशील/स्थैतिक बहुरूपता अनुप्रयोग डिजाइन और आवश्यकताओं पर निर्भर करती है। हालांकि, क्या यह सलाह दी जाती है कि यदि संभव हो तो गतिशील पर स्थैतिक बहुरूपता का चयन करें? जबकि अभी भी टेम्पलेट के रूप में एक इंटरफेस प्रदान नहीं vtable देखने भूमि के ऊपर: विशेष रूप से, मैं अपने आवेदन में निम्नलिखित 2 डिजाइन विकल्प देख सकते हैं, जो दोनों के खिलाफ की सलाह दी हो रहे हैं:सी ++ में डायामी बनाम स्टेटिक पॉलिमॉर्फिज्म: जो बेहतर है?

  1. CRTP का उपयोग कर स्टेटिक बहुरूपता लागू आधार वर्ग लेकिन, सही वर्ग/विधि है, जो खतरनाक

  2. गतिशील बहुरूपता है उपयोग करने के लिए स्विच और static_cast का उपयोग किया:, इंटरफेस (शुद्ध आभासी वर्ग) को लागू की तरह accessors/mutators भी तुच्छ कार्यों के लिए देखने लागत जोड़

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

संपादित करें: अंतर्दृष्टि के लिए धन्यवाद। एक विशिष्ट मामला लेना, इनमें से कौन सा बेहतर दृष्टिकोण है?

class IMessage_Type_1 
{ 
    virtual long getQuantity() =0; 
... 
} 
class Message_Type_1_Impl: public IMessage_Type_1 
{ 
    long getQuantity() { return _qty;} 
... 
} 

या

template <class T> 
class TMessage_Type_1 
{ 
    long getQuantity() { return static_cast<T*>(this)->getQuantity(); } 
... 
} 
class Message_Type_1_Impl: public TMessage_Type_1<Message_Type_1_Impl> 
{ 
    long getQuantity() { return _qty; } 
... 
} 

नोट कई mutators/प्रत्येक वर्ग में accessors देखते हैं, और मैं अपने आवेदन में एक अंतरफलक निर्दिष्ट करने की आवश्यकता है कि। स्थिर polymorphism में, मैं सिर्फ एक बार स्विच - संदेश प्रकार प्राप्त करने के लिए। हालांकि, गतिशील बहुरूपता में, मैं प्रत्येक विधि कॉल के लिए वर्चुअल फ़ंक्शंस का उपयोग कर रहा हूं। क्या यह स्थिर पॉली का उपयोग करने का मामला नहीं बनाता है? मेरा मानना ​​है कि सीआरटीपी में static_cast काफी सुरक्षित है और कोई प्रदर्शन जुर्माना नहीं है (समयबद्ध संकलन)?

+4

एक स्विच-केस संरचना में एक vtable का उपयोग करने के समान जटिलता है। – user877329

+0

मुझे यकीन नहीं है कि आप स्थिर पॉलीमोर्फिज्म का उपयोग करते समय बहुत सारे static_cast और स्विच के साथ क्यों समाप्त होते हैं - क्या आप कुछ उदाहरण कोड दिखा सकते हैं? –

+1

@ माइकल एंडरसन: यदि आप एक ऐसी स्थिति में स्थैतिक बहुरूपता का उपयोग करने की कोशिश करते हैं, जिसके लिए गतिशील बहुरूपता की आवश्यकता होती है तो आपको वह मिल जाएगा। उस स्थिति में इसे फिर से शुरू करने की कोशिश करने के बजाय गतिशील बहुरूपता का उपयोग करना लगभग निश्चित रूप से बेहतर होता है। –

उत्तर

8

एक स्विच कूद के अनुक्रम से अधिक कुछ नहीं है जिसके बाद अनुकूलित किया गया- एक तालिका द्वारा देखा गया पता लगाने के लिए कूद जाता है। वर्चुअल फ़ंक्शन कॉल की तरह बिल्कुल।

यदि आपको किसी प्रकार के आधार पर कूदना है, तो आपको पहले प्रकार का चयन करना होगा। यदि चयन संकलन समय पर नहीं किया जा सकता है (अनिवार्य रूप से क्योंकि यह इनपुट पर निर्भर करता है) तो आपको हमेशा दो ऑपरेशन करना होगा: & कूदें चुनें। सिंटैक्टिक टूल जो आप चुनने के लिए उपयोग करते हैं, प्रदर्शन को परिवर्तित नहीं करते हैं, क्योंकि इसे अनुकूलित करें।

वास्तव में आप v-table reinventing हैं।

+0

मैं मानता हूं कि स्विच केस मूल रूप से एक vtable है। हालांकि, गतिशील बहुरूपता में, हम प्रत्येक विधि के लिए वर्चुअल का उपयोग करते हैं, जबकि स्थिर में हमें व्युत्पन्न प्रकार प्राप्त करने के लिए एक बार स्विच और कास्ट करने के लिए उपयोग करने की आवश्यकता होती है, उसके बाद कोई संकेत नहीं होता है। प्रश्न में एक उदाहरण जोड़ा गया। क्या इसे लागू करने का कोई बेहतर तरीका है? – vid

+0

@vid: अगर कॉलर को व्युत्पन्न प्रकार के बारे में जानने की अनुमति है, तो पॉलिमोफिज्म का उद्देश्य क्या है? इस मामले फोन करने वाले व्युत्पन्न वर्ग के साथ सीधे बातचीत कर सकते हैं, किसी भी संक्षेपण हैं, इंटरफेस के बिना, आदि लगता है दोनों polymorhism और विरासत यहां बेमानी हैं। फोन करने वाले व्युत्पन्न प्रकार के बारे में पता करने की अनुमति नहीं है, तो तो प्रकार कास्टिंग और विधि भेजने आधार वर्ग के अंदर प्रत्येक कॉल पर किया जाना चाहिए। vtable इस तरह के प्रेषण के लिए इष्टतम समाधान है। सीआरपीटी आधार से व्युत्पन्न कक्षा (केवल) – user396672

+0

से कॉल अनुकूलित करने का सही टूल है, ठीक है, मैं आपके बिंदु की सराहना करता हूं। मैं जो करने की कोशिश कर रहा था वह सीआरटीपी का उपयोग कर एक इंटरफ़ेस निर्दिष्ट किया गया था। इसलिए, जब अन्य डेवलपर लाइब्रेरी का विस्तार करना चाहते हैं, तो वे फिर से सीआरटीपी का उपयोग कर बेस क्लास का उत्तराधिकारी होते हैं, और अगर वे किसी भी विधि को लागू करने में असफल होते हैं तो एक संकलन त्रुटि फेंक दी जाती है। शुद्ध वर्चुअल बेस क्लास के समान तर्क, लेकिन vtable ओवरहेड के बिना। क्या कोई मुहावरे है जो मैं सोच सकता हूं कि यह अधिक उचित तरीके से लागू करता है? – vid

6

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

दूसरी तरफ, वर्चुअल फ़ंक्शंस का उपयोग करते समय आप प्रदर्शन समस्याओं से डरते हैं। यह साबित करना कि यह एक समस्या होगी बहुत कठिन है।

आईएमएचओ यह एक गैर-प्रश्न है। अन्यथा इंगित किए जाने तक आभासी कार्यों के साथ चिपकाएं। वर्चुअल फ़ंक्शन कॉल अधिकांश लोगों के विचार से बहुत तेज़ होते हैं (एक गतिशील रूप से लिंक्ड लाइब्रेरी से फ़ंक्शन को कॉल करना भी संकेत की एक परत जोड़ता है। कोई भी इसके बारे में सोचना नहीं चाहता)।

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

+0

धन्यवाद @ebo।मैं अपने आवेदन में एक बाधा के रूप में आभासी कार्यों को सक्रिय करता हूं, ओवरहेड स्पष्ट बनाने के लिए प्रश्न संपादित करता हूं – vid

14

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

दोनों का एक मोटा वर्गीकरण: वर्चुअल फ़ंक्शंस एक सामान्य इंटरफ़ेस के लिए अलग कार्यान्वयन की अनुमति देता है; टेम्पलेट्स एक आम कार्यान्वयन के लिए विभिन्न इंटरफेस की अनुमति देते हैं।

+0

'आभासी फ़ंक्शन एक सामान्य इंटरफ़ेस के लिए विभिन्न कार्यान्वयन की अनुमति देते हैं; टेम्पलेट्स एक आम कार्यान्वयन के लिए अलग-अलग इंटरफेस की अनुमति देते हैं। 'यह वास्तव में समझ में नहीं आता है। स्टेटिक पॉलिमॉर्फिज्म वास्तव में दो अलग-अलग वर्गों को अपना कार्यान्वयन करने की इजाजत दे रहा है, लेकिन विधि का एक ही नाम है और बेस क्लास से दोनों मामलों में बुलाया जाता है। – johnbakers

+1

@ फेलोशीहे सबसे आम उपयोग में, एक टेम्पलेट क्लास एक अलग इंटरफ़ेस प्रदान करता है, लेकिन प्रत्येक कार्यान्वयन प्रकार के लिए एक ही कार्यान्वयन: उदा। 'Std :: वेक्टर ' एक 'push_back (डबल)' समारोह है, जहां के रूप में 'std :: वेक्टर ' 'प्रदान करता है push_back (int)' प्रदान करता है। विभिन्न इंटरफेस; एक ही कार्यान्वयन। वर्चुअल 'push_back (डबल)' से विरासत विभिन्न कार्यान्वयन की अनुमति देगा, लेकिन एक अलग इंटरफ़ेस की अनुमति नहीं देगा। –

1

स्थिर पॉलिमॉर्फिज्म महत्वपूर्ण लाभ प्रदान कर सकता है यदि कॉल किए गए विधि को कंपाइलर द्वारा रेखांकित किया जा सकता है। उदाहरण के लिए, आभासी विधि इस तरह दिखता है:

protected: 
virtual bool is_my_class_fast_enough() override {return true;} 

तो स्थिर polimophism पसंदीदा तरीका (अन्यथा, विधि ईमानदार होना और वापसी झूठी :) चाहिए होना चाहिए।

"ट्रू" वर्चुअल कॉल (ज्यादातर मामलों में) को रेखांकित नहीं किया जा सकता है।

(जैसे vtable कॉल में अतिरिक्त अविवेक के रूप में) अन्य मतभेदों neglectable हैं

[संपादित करें]

हालांकि, अगर आप वास्तव में क्रम बहुरूपता (की जरूरत है फोन करने वाले को पता नहीं करना चाहिए विधि के कार्यान्वयन और इसलिए, विधि को कॉलर के पक्ष में रेखांकित नहीं किया जा सकता है) तो vtable को पुन: पेश नहीं करें (जैसा कि एमिलियो गरवाग्लिया का उल्लेख है), बस इसका उपयोग करें।

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