2008-11-06 21 views
19

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

मैं क्या जानना चाहता हूं कि क्यों सी ++ ऐसी सुविधा की अनुमति देने के लिए डिज़ाइन नहीं किया गया है। कक्षा के निजी हिस्सों के लिए यह शीर्ष पर खुले तौर पर प्रदर्शित होने की मांग क्यों करता है (कोई इरादा नहीं है)?

+0

@ फ़्रेडरिक, आप "बूब" नहीं हैं, यह एक अच्छा सवाल है! – jwfearn

+0

अच्छी तरह से देखा (पन इरादा)! –

उत्तर

10

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

आप अनुकरण कर सकते हैं, हालांकि, का पालन करके अपने वांछित व्यवहार:

class MyClass 
{ 
public: 
    // public stuff 

private: 
#include "MyClassPrivate.h" 
}; 

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

+0

लेकिन निश्चित रूप से! मैं उस सवाल से पूछने के लिए कितना उत्साहित हूं। वैसे भी सभी को धन्यवाद। –

+0

एक और नकारात्मक बात यह है कि निजी इंटरफेस में बदलाव के लिए अभी भी ग्राहकों के पुनर्मूल्यांकन की आवश्यकता है। – peterchen

+4

यह उत्तर क्यों स्वीकार किया जाता है? "MyClassPrivate.h" को मूल हेडर के रूप में आसानी से पढ़ा जा सकता है। यह अभी भी recompile की आवश्यकता है। वस्तु का आकार एक मामूली मुद्दा है। सच्चे शो-स्टॉपर्स कुछ सी मुहावरे के साथ दक्षता और पिछड़े-अनुकूलता हैं। – jfs

3

हो सकता है क्योंकि कक्षा के आकार की आवश्यकता होती है जब मूल्यों द्वारा इसका उदाहरण पारित किया जाता है, इसे अन्य वर्गों में एकत्रित किया जाता है आदि?

यदि सी ++ मूल्य अर्थशास्त्र का समर्थन नहीं करता है, तो यह ठीक होता, लेकिन ऐसा होता है।

+0

ऐसा नहीं है कि सी ++ मूल्य अर्थशास्त्र का समर्थन करता है ... यह है कि सी ++ वास्तव में उन अर्थशास्त्र प्रदान करने के लिए मूल्य से विश्लेषण करेगा (जो सबसे कुशल और सरल दृष्टिकोण है, वैसे भी)। – Arafangion

+0

@Ara: क्या आप "मूल्य से पार्स" शब्द पर विस्तार कर सकते हैं? मैंने इसके बारे में कभी नहीं सुना। – fredoverflow

+0

@ फ्रेड: ओह, आपने मेरा एक टाइपो पकड़ा है - मैं करता हूं, वास्तव में, मतलब पास है।:) – Arafangion

5

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

भाषा पहले से ही काफी जटिल है; मुझे लगता है कि कोड में संरचित डेटा की परिभाषाओं को विभाजित करने के लिए एक तंत्र एक आपदा का थोड़ा सा होगा।

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

3

हाँ, पर ...

आप Stroustrup की "डिजाइन और सी के विकास ++" पुस्तक पढ़ने की जरूरत है। यह सी ++ के उत्थान को रोक देगा।

क्यों डेवलपर pimpl कोड बाहर टाइप करना होगा -

6

आप सभी प्रश्न की बात की अनदेखी कर रहे हैं?

मेरे लिए, सबसे अच्छा जवाब मैं साथ आ सकता हूं कि हमारे पास सी ++ कोड व्यक्त करने का एक अच्छा तरीका नहीं है जो आपको इसे संचालित करने की अनुमति देता है। उदाहरण के लिए, संकलन-समय (या प्री-प्रोसेसर, या जो कुछ भी) प्रतिबिंब या कोड डोम।

सी ++ को मेटा-प्रोग्रामिंग करने के लिए डेवलपर को उपलब्ध होने के लिए इनमें से एक या दोनों को बुरी तरह की आवश्यकता है।

फिर आप अपने सार्वजनिक MyClass में ऐसा कुछ लिख सकते हैं।एच:

#pragma pimpl(MyClass_private.hpp) 

और फिर अपना खुद का, वास्तव में काफी छोटा रैपर जनरेटर लिखें।

9

मुझे लगता है कि यहां एक भ्रम है। समस्या हेडर के बारे में नहीं है। शीर्षलेख कुछ भी नहीं करते हैं (वे कई स्रोत-कोड फ़ाइलों के बीच स्रोत टेक्स्ट के सामान्य बिट्स को शामिल करने के तरीके हैं)।

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

यह सामान्य ऑब्जेक्ट ओरिएंटेड टेक्नोलॉजीज की प्रकृति में है (केवल सी ++ एक नहीं) कि किसी को कार्यान्वित करने के लिए उपयोग किए जाने वाले ठोस वर्ग और उसके कन्स्ट्रक्टर का उपयोग करने की आवश्यकता है, भले ही आप केवल सार्वजनिक भागों का उपयोग कर रहे हों। डिवाइस (3, नीचे) इसे छुपाता है। (1, नीचे) में अभ्यास चिंताओं को अलग करता है, चाहे आप (3) हों या नहीं।

  1. अमूर्त वर्गों का उपयोग करें जो केवल सार्वजनिक भागों को परिभाषित करते हैं, मुख्य रूप से विधियों, और कार्यान्वयन वर्ग को उस सार वर्ग से प्राप्त करते हैं। तो, हेडर के लिए सामान्य सम्मेलन का उपयोग करते हुए, एक सार.hpp है जो आसपास साझा किया जाता है। एक कार्यान्वयन.hpp भी है जो विरासत वर्ग घोषित करता है और यह केवल मॉड्यूल के आसपास पारित होता है जो कार्यान्वयन के तरीकों को लागू करता है। कार्यान्वयन.hpp फ़ाइल उस वर्ग घोषणा में उपयोग के लिए "abstract.hpp" शामिल करेगी, ताकि सारणित इंटरफ़ेस की घोषणा के लिए एक ही रखरखाव बिंदु हो।

  2. अब, यदि आप कार्यान्वयन कक्षा घोषणा के छिपाने को लागू करना चाहते हैं, तो आपको विशिष्ट, पूर्ण श्रेणी घोषणा के बिना ठोस उदाहरण के निर्माण का अनुरोध करने का कोई तरीका होना चाहिए: आप नए का उपयोग नहीं कर सकते हैं और आप कर सकते हैं स्थानीय उदाहरणों का उपयोग नहीं करते हैं। (हालांकि आप हटा सकते हैं।) सहायक कार्यों का परिचय (कक्षा के उदाहरणों के संदर्भ देने वाले अन्य वर्गों पर विधियों सहित) विकल्प है।

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

मिशन पूरा हुआ।

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

+0

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

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