क्या pImpl मुहावरा वास्तव में व्यवहार में उपयोग किया जाता है?


165

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

उदाहरण के लिए:

class X
{
private:
  C c;
  D d;  
} ;

इसे बदला जा सकता है:

class X
{
private:
  struct XImpl;
  XImpl* pImpl;       
};

और, सीपीपी में, परिभाषा:

struct X::XImpl
{
  C c;
  D d;
};

यह काफी दिलचस्प लगता है, लेकिन मैंने इस तरह का दृष्टिकोण पहले कभी नहीं देखा है, न तो मैंने जिन कंपनियों में काम किया है, और न ही ओपन सोर्स प्रोजेक्ट्स में मैंने सोर्स कोड देखा है। इसलिए, मुझे आश्चर्य है कि यह तकनीक वास्तव में व्यवहार में उपयोग की जाती है?

क्या मुझे इसे हर जगह, या सावधानी के साथ उपयोग करना चाहिए? और क्या इस तकनीक को एम्बेडेड सिस्टम (जहां प्रदर्शन बहुत महत्वपूर्ण है) में उपयोग करने की सिफारिश की गई है?


क्या यह अनिवार्य रूप से निर्णय लेने के समान है कि X एक (सार) इंटरफ़ेस है, और Ximpl कार्यान्वयन है? struct XImpl : public X। यह मुझे अधिक स्वाभाविक लगता है। क्या कोई और मुद्दा है जो मैंने याद किया है?
आरोन मैकडैड

@AaronMcDaid: यह समान है, लेकिन इसके फायदे हैं कि (ए) सदस्य कार्यों को आभासी होने की जरूरत नहीं है, और (बी) आपको इसे पलटने के लिए किसी कारखाने, या कार्यान्वयन वर्ग की परिभाषा की आवश्यकता नहीं है।
माइक सेमुर

2
@AaronMcDaid pimpl मुहावरा आभासी फ़ंक्शन कॉल से बचा जाता है। यह थोड़ा और भी C ++ - ish (C ++ - ish के कुछ गर्भाधान के लिए) है; आप कारखाने के कार्यों के बजाय निर्माणकर्ताओं को आमंत्रित करते हैं। मैंने दोनों का उपयोग किया है, जो मौजूदा कोड बेस में है, उसके आधार पर --- pimpl मुहावरा (मूल रूप से चेशायर बिल्ली मुहावरा कहा जाता है, और कम से कम 5 वर्षों से हर्ब के वर्णन से पहले) एक लंबा इतिहास है और अधिक होने लगता है व्यापक रूप से C ++ में उपयोग किया जाता है, लेकिन अन्यथा, दोनों काम करते हैं।
जेम्स कांजे

30
C ++ में, pimpl के const unique_ptr<XImpl>बजाय के साथ लागू किया जाना चाहिए XImpl*
नील जी

1
"इस तरह का दृष्टिकोण पहले कभी नहीं देखा, न तो जिन कंपनियों में मैंने काम किया है, न ही ओपन सोर्स प्रोजेक्ट्स में"। क्यूटी शायद ही कभी इसका उपयोग नहीं कर रहा है।
मैनुएल श्नाइड 3r 25'15

जवाबों:


132

इसलिए, मुझे आश्चर्य है कि यह तकनीक वास्तव में व्यवहार में उपयोग की जाती है? क्या मुझे इसे हर जगह, या सावधानी के साथ उपयोग करना चाहिए?

बेशक इसका उपयोग किया जाता है। मैं इसे लगभग हर वर्ग में अपने प्रोजेक्ट में इस्तेमाल करता हूँ।


PIMPL मुहावरे का उपयोग करने के कारण:

बाइनरी संगतता

जब आप एक पुस्तकालय विकसित कर रहे हैं, तो आप XImplअपने ग्राहक के साथ द्विआधारी संगतता को तोड़ने के बिना / जोड सकते हैं / संशोधित कर सकते हैं (जिसका अर्थ क्रैश होगा!)। चूँकि Xजब आप नए फ़ील्ड्स को Ximplक्लास में जोड़ते हैं तो क्लास का बाइनरी लेआउट नहीं बदलता है , यह मामूली संस्करणों के अपडेट में लाइब्रेरी में नई कार्यक्षमता जोड़ने के लिए सुरक्षित है।

बेशक, आप द्विआधारी संगतता को तोड़ने के बिना X/ के XImplबिना नए सार्वजनिक / निजी गैर-आभासी तरीकों को भी जोड़ सकते हैं , लेकिन यह मानक हेडर / कार्यान्वयन तकनीक के बराबर है।

डेटा छिपाना

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

संकलन का समय

संकलन का समय कम हो जाता है, क्योंकि Xजब आप फ़ील्ड जोड़ते हैं और हटाते हैं , तो केवल स्रोत (कार्यान्वयन) की फ़ाइल को XImplवर्ग में और / या विधियों को जोड़ा जाता है (जो मानक तकनीक में निजी क्षेत्रों / विधियों को जोड़ने के लिए मैप करता है)। व्यवहार में, यह एक सामान्य ऑपरेशन है।

मानक हेडर / कार्यान्वयन तकनीक (PIMPL के बिना) के साथ, जब आप एक नया क्षेत्र जोड़ते हैं X, तो हर ग्राहक जो कभी भी आवंटित करता है X(या तो ढेर पर, या ढेर पर) उसे फिर से जोड़ने की आवश्यकता होती है, क्योंकि उसे आवंटन के आकार को समायोजित करना होगा। खैर, हर ग्राहक कभी आवंटित नहीं है कि एक्स भी कंपाइल करने की आवश्यकता है, लेकिन यह सिर्फ भूमि के ऊपर (क्लाइंट साइड पर जिसके परिणामस्वरूप कोड एक ही हो जाएगा) है।

क्या अधिक है, मानक हेडर / क्रियान्वयन पृथक्करण के साथ XClient1.cppभी जब एक निजी विधि X::foo()को जोड़ा Xऔर X.hबदला गया, तब भी इसे पुन: संकलित करने की आवश्यकता होती है , भले ही XClient1.cppसंभवतः इस विधि को एनकैप्सुलेशन कारणों से नहीं कहा जा सकता है! ऊपर की तरह, यह शुद्ध उपरि है और वास्तविक जीवन C ++ बिल्ड सिस्टम के काम करने के तरीके से संबंधित है।

बेशक, पुनर्संयोजन की आवश्यकता नहीं है जब आप सिर्फ तरीकों के कार्यान्वयन को संशोधित करते हैं (क्योंकि आप हेडर को नहीं छूते हैं), लेकिन यह मानक हेडर / कार्यान्वयन तकनीक के बराबर है।


क्या इस तकनीक को एम्बेडेड सिस्टम (जहां प्रदर्शन बहुत महत्वपूर्ण है) में उपयोग करने की सिफारिश की गई है?

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


16
+1 क्योंकि यह व्यापक रूप से उस कंपनी में उपयोग किया जाता है जिसके लिए मैं काम करता हूं, और उसी कारणों से।
बेनोइट

9
इसके अलावा, द्विआधारी संगतता
अंबोज़ बिज्जक

9
Qt लाइब्रेरी में इस पद्धति का उपयोग स्मार्ट पॉइंटर स्थितियों में भी किया जाता है। इसलिए QString आंतरिक रूप से एक अपरिवर्तनीय वर्ग के रूप में अपनी सामग्री रखता है। जब पब्लिक क्लास को "कॉपी" किया जाता है, तो प्राइवेट मेंबर के पॉइंटर को पूरे प्राइवेट क्लास के बजाय कॉपी किया जाता है। ये निजी कक्षाएं तब स्मार्ट पॉइंटर्स का भी उपयोग करती हैं, इसलिए आप मूल रूप से अधिकांश कक्षाओं के साथ कचरा संग्रह प्राप्त करते हैं, इसके अलावा पूर्ण कक्षा की नकल के बजाय पॉइंटर कॉपी के कारण बहुत बेहतर प्रदर्शन
टिमोथी बाल्ड्रिज

8
इससे भी अधिक, pimpl मुहावरे के साथ Qt एक ही प्रमुख संस्करण (ज्यादातर मामलों में) के भीतर आगे और पीछे बाइनरी संगतता दोनों को बनाए रख सकता है। IMO यह अब तक इसका उपयोग करने का सबसे महत्वपूर्ण कारण है।
श्वेतार्क

1
यह प्लेटफ़ॉर्म-विशिष्ट कोड को लागू करने के लिए भी उपयोगी है, क्योंकि आप एक ही एपीआई को बनाए रख सकते हैं।
doc

49

ऐसा लगता है कि बहुत से पुस्तकालयों का उपयोग अपने एपीआई में स्थिर रहने के लिए करते हैं, कम से कम कुछ संस्करणों के लिए।

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

फायदे यह हो सकता है आप दे रहे हैं:

  • साझा पुस्तकालयों की द्विआधारी संगतता रखने में मदद करता है
  • कुछ आंतरिक विवरणों को छिपाना
  • घटते पुनरावर्तन चक्र

वे आपके लिए वास्तविक लाभ हो भी सकते हैं और नहीं भी। मेरे लिए की तरह, मैं कुछ मिनट के पुनर्मिलन के समय की परवाह नहीं करता। अंत उपयोगकर्ता आमतौर पर भी नहीं करते हैं, क्योंकि वे हमेशा इसे एक बार और शुरुआत से संकलित करते हैं।

संभावित नुकसान हैं (यहां भी, कार्यान्वयन के आधार पर और क्या वे आपके लिए वास्तविक नुकसान हैं):

  • भोले रूप के साथ अधिक आवंटन के कारण स्मृति उपयोग में वृद्धि
  • रखरखाव के प्रयास में वृद्धि (आपको कम से कम अग्रेषण कार्यों को लिखना होगा)
  • प्रदर्शन हानि (संकलक इनलाइन सामान को सक्षम नहीं कर सकता है क्योंकि यह आपके वर्ग के भोलेपन के साथ है)

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

लिनक्स statकॉल के लिए मेरा सी ++ रैपर । यहां सी हेडर से संरचना अलग हो सकती है, जो #definesसेट पर निर्भर करता है । और जब से मेरे रैपर हेडर उन सभी को नियंत्रित नहीं कर सकते, मैं केवल #include <sys/stat.h>अपनी .cxxफ़ाइल में और इन समस्याओं से बचता हूं ।


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

5
@JamesKanze: यहां तक ​​कि मैं व्यक्तिगत रूप से एक पल के लिए बैठूंगा और सोचूंगा कि क्या यह #ifdefसंभव नहीं है कि रैपर को जितना संभव हो उतना पतला करने के लिए कुछ एस होना चाहिए। लेकिन हर किसी के पास अलग-अलग लक्ष्य होते हैं, महत्वपूर्ण बात यह है कि किसी चीज का आंख मूंदकर पालन करने के बजाय उस पर सोचने का समय निकालें।
प्लाज़्मा एचएच

31

सामानों के बारे में सभी अन्य लोगों से सहमत हैं, लेकिन मुझे सबूतों की सीमा में रहने दें: टेम्पलेट के साथ अच्छी तरह से काम नहीं करता है

कारण यह है कि टेम्प्लेट इंस्टेंटेशन के लिए पूर्ण घोषणा की आवश्यकता होती है, जहाँ इंस्टेंटेशन हुआ। (और यह मुख्य कारण है कि आप सीपीपी फाइलों में परिभाषित टेम्प्लेट विधियों को नहीं देखते हैं)

आप अभी भी टेम्पर्ड सबक्लास का उल्लेख कर सकते हैं, लेकिन जब से आपको उन सभी को शामिल करना है, संकलन पर "कार्यान्वयन डिकॉउलिंग" का हर लाभ (सभी प्लाटोफॉर्म विशिष्ट कोड को हर जगह शामिल करने से परहेज करना, संकलन को छोटा करना) खो जाता है।

क्लासिक OOP (विरासत आधारित) के लिए एक अच्छा प्रतिमान है, लेकिन सामान्य प्रोग्रामिंग (विशेषज्ञता आधारित) के लिए नहीं।


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

22

अन्य लोगों ने पहले ही तकनीकी अप / डाउनसाइड प्रदान किया है, लेकिन मुझे लगता है कि निम्नलिखित ध्यान देने योग्य है:

सबसे पहले और सबसे महत्वपूर्ण, हठधर्मिता नहीं है। यदि pImpl आपकी स्थिति के लिए काम करता है, तो इसका उपयोग करें - इसे केवल इसलिए उपयोग न करें क्योंकि "यह बेहतर OO है क्योंकि यह वास्तव में कार्यान्वयन को छुपाता है" आदि C ++ FAQ को उद्धृत करते हुए:

एन्कैप्सुलेशन कोड के लिए है, न कि लोग ( स्रोत )

OpenThreads, थ्रेडिंग द्वारा इस्तेमाल किया पुस्तकालय: बस आप जहां यह प्रयोग किया जाता है खुला स्रोत सॉफ्टवेयर का एक उदाहरण है और क्यों देने के लिए OpenSceneGraph । मुख्य विचार शीर्षलेख (जैसे <Thread.h>) सभी प्लेटफ़ॉर्म-विशिष्ट कोड से निकालना है , क्योंकि आंतरिक राज्य चर (जैसे थ्रेड हैंडल) प्लेटफ़ॉर्म से प्लेटफ़ॉर्म से भिन्न होते हैं। इस तरह से कोई भी आपके पुस्तकालय के खिलाफ दूसरे प्लेटफार्मों के किसी भी ज्ञान के बिना कोड को संकलित कर सकता है, क्योंकि सब कुछ छिपा हुआ है।


12

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

हर वर्ग के लिए PIMPL का उपयोग करने के लिए, मैं सावधानी से विचार करूंगा क्योंकि उन सभी लाभों को एक लागत पर आता है: कार्यान्वयन के तरीकों का उपयोग करने के लिए अप्रत्यक्ष स्तर का एक अतिरिक्त स्तर आवश्यक है।


"कार्यान्वयन विधियों तक पहुँचने के लिए अप्रत्यक्ष स्तर का एक अतिरिक्त स्तर आवश्यक है।" यह है?
xaxxon

@xaxxon हाँ, यह है। अगर विधि निम्न स्तर की है तो पिंपल धीमा है। उदाहरण के लिए, एक तंग पाश में रहने वाले सामान के लिए इसका उपयोग कभी न करें।
एरिक एरोनसिटी

@xaxxon मैं सामान्य मामले में कहूंगा कि एक अतिरिक्त स्तर की आवश्यकता है। यदि इनलाइनिंग नहीं की तुलना में किया जाता है। लेकिन इनलाइनिंग एक अलग डीएल में संकलित कोड में एक विकल्प नहीं होगा।
घिता

5

मुझे लगता है कि यह डिकॉउलिंग के लिए सबसे बुनियादी उपकरणों में से एक है।

मैं एम्बेडेड प्रोजेक्ट (सेटटॉप बॉक्स) पर पिम्पल (और असाधारण सी ++ से कई अन्य मुहावरों) का उपयोग कर रहा था।

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


4

मैं इस तकनीक का इस्तेमाल अतीत में बहुत करता था लेकिन फिर खुद को इससे दूर होता हुआ पाया।

बेशक यह एक अच्छा विचार है कि कार्यान्वयन विवरण को अपनी कक्षा के उपयोगकर्ताओं से दूर छिपाएं। हालाँकि आप यह भी कर सकते हैं कि कक्षा के उपयोगकर्ताओं को अमूर्त इंटरफ़ेस का उपयोग करने के लिए और कार्यान्वयन विवरण के लिए ठोस वर्ग होने के लिए।

PImpl के फायदे हैं:

  1. यह मानते हुए कि इस इंटरफ़ेस का सिर्फ एक कार्यान्वयन है, यह अमूर्त वर्ग / कंक्रीट कार्यान्वयन का उपयोग नहीं करके स्पष्ट है

  2. यदि आपके पास वर्गों (एक मॉड्यूल) का एक सूट है, तो कई कक्षाएं समान "प्रत्यारोपण" तक पहुंचती हैं, लेकिन मॉड्यूल के उपयोगकर्ता केवल "उजागर" कक्षाओं का उपयोग करेंगे।

  3. अगर इसे गलत बात माना जाए तो कोई वी-टेबल नहीं।

मुझे pImpl का नुकसान मिला (जहाँ अमूर्त इंटरफ़ेस बेहतर काम करता है)

  1. जब तक आपके पास केवल एक "उत्पादन" कार्यान्वयन हो सकता है, एक सार इंटरफ़ेस का उपयोग करके आप इकाई परीक्षण में काम करने वाले "मॉक" कार्यान्वयन को भी बना सकते हैं।

  2. (सबसे बड़ा मुद्दा)। Unique_ptr और बढ़ने के दिनों से पहले आपके पास विकल्प थे कि कैसे pImpl को स्टोर किया जाए। एक कच्चा सूचक और आपके पास आपकी कक्षा के गैर-प्रतिलिपि होने के बारे में समस्या थी। एक पुराना auto_ptr आगे घोषित वर्ग के साथ काम नहीं करेगा (वैसे भी सभी संकलक पर नहीं)। इसलिए लोगों ने share_ptr का उपयोग करना शुरू कर दिया, जो आपकी कक्षा को प्रतिलिपि बनाने में अच्छा था लेकिन निश्चित रूप से दोनों प्रतियों में एक ही अंतर्निहित साझा किया गया था जिसे आप उम्मीद नहीं कर सकते हैं (एक को संशोधित करें और दोनों को संशोधित किया गया है)। इसलिए समाधान अक्सर एक के लिए कच्चे पॉइंटर का उपयोग करना था और कक्षा को गैर-प्रतिलिपि बनाने योग्य था और इसके बजाय एक साझा_पार्ट लौटाया। तो दो नए को बुलाता है। (वास्तव में 3 दिए गए पुराने शेयर्ड_एप्ट्र ने आपको एक दूसरा दिया)।

  3. तकनीकी रूप से वास्तव में कब्ज सही नहीं है क्योंकि सदस्य के सूचक के माध्यम से कब्ज का प्रसार नहीं होता है।

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


3

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


3

यहाँ एक वास्तविक परिदृश्य है जिसका मैंने सामना किया, जहाँ इस मुहावरे ने बहुत मदद की। मैंने हाल ही में डायरेक्टएक्स 11 का समर्थन करने का फैसला किया है, साथ ही मेरे मौजूदा डायरेक्टएक्स 9 का समर्थन, एक गेम इंजन में। इंजन पहले से ही अधिकांश डीएक्स विशेषताओं को लपेटता है, इसलिए डीएक्स इंटरफेस में से कोई भी सीधे इस्तेमाल नहीं किया गया था; वे सिर्फ हेडर में निजी सदस्यों के रूप में परिभाषित किए गए थे। इंजन कीबोर्ड, माउस, जॉयस्टिक और स्क्रिप्टिंग सपोर्ट को जोड़कर डीएलएल को कई अन्य एक्सटेंशन के रूप में उपयोग करता है। जबकि उन DLL में से अधिकांश ने सीधे DX का उपयोग नहीं किया था, उन्हें DX को ज्ञान और लिंकेज की आवश्यकता थी क्योंकि उन्होंने DX को उजागर करने वाले हेडर में खींच लिया था। DX 11 को जोड़ने में, यह जटिलता नाटकीय रूप से बढ़नी थी, लेकिन अनावश्यक रूप से। केवल एक स्रोत में परिभाषित Pimpl में DX के सदस्यों को ले जाने से इस आरोप को समाप्त किया गया। पुस्तकालय निर्भरता में इस कमी के शीर्ष पर,


2

इसका उपयोग बहुत सारी परियोजनाओं में किया जाता है। यह उपयोगिता की तरह परियोजना पर निर्भर करता है। इसका उपयोग करने वाली अधिक प्रमुख परियोजनाओं में से एक Qt है , जहां मूल विचार उपयोगकर्ता से कार्यान्वयन या platformspecific कोड को छिपाने के लिए है (Qt का उपयोग कर अन्य डेवलपर्स)।

यह एक अच्छा विचार है, लेकिन इसके लिए एक वास्तविक खामी है: डिबगिंग जब तक निजी उपकरणों में छिपा हुआ कोड प्रीमियम गुणवत्ता का है, यह सब ठीक है, लेकिन अगर इसमें कीड़े हैं, तो उपयोगकर्ता / डेवलपर को एक समस्या है, क्योंकि यह एक छिपे हुए कार्यान्वयन के लिए सिर्फ एक गूंगा सूचक है, भले ही उसके पास कार्यान्वयन स्रोत कोड हो।

तो लगभग सभी डिजाइन निर्णयों के रूप में वहाँ एक पेशेवरों और विपक्ष।


9
यह गूंगा है, लेकिन यह टाइप किया गया है ... आप डिबगर में कोड का पालन क्यों नहीं कर सकते?
अंकलजीव

2
सामान्यतया, Qt कोड में डीबग करने के लिए आपको स्वयं Qt बनाने की आवश्यकता होती है। एक बार जब आप करते हैं, तो PIMPL तरीकों में कदम रखने और PIMPL डेटा की सामग्री का निरीक्षण करने में कोई समस्या नहीं है।
मोनिका

0

एक लाभ मुझे यह देखने को मिल सकता है कि यह प्रोग्रामर को कुछ कार्यों को काफी तेज तरीके से लागू करने की अनुमति देता है:

X( X && move_semantics_are_cool ) : pImpl(NULL) {
    this->swap(move_semantics_are_cool);
}
X& swap( X& rhs ) {
    std::swap( pImpl, rhs.pImpl );
    return *this;
}
X& operator=( X && move_semantics_are_cool ) {
    return this->swap(move_semantics_are_cool);
}
X& operator=( const X& rhs ) {
    X temporary_copy(rhs);
    return this->swap(temporary_copy);
}

पुनश्च: मुझे उम्मीद है कि मैं गलत अर्थों में कदम नहीं कर रहा हूँ।

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