निजी चर सार्वजनिक रूप से सुलभ हेडर फ़ाइल में क्यों वर्णित हैं?


11

ठीक है, इसलिए उम्मीद है कि यह प्रोग्रामर के लिए एक व्यक्तिपरक पर्याप्त प्रश्न है, लेकिन यहां जाता है। मैं भाषाओं और सॉफ्टवेयर इंजीनियरिंग प्रथाओं के अपने ज्ञान को लगातार बढ़ा रहा हूं ... और मैंने कुछ ऐसा किया है जिससे मुझे कोई मतलब नहीं है।

C ++ में, क्लास की घोषणाओं में private:हेडर फ़ाइल में तरीके और पैरामीटर शामिल होते हैं , जो, सैद्धांतिक रूप से, यह है कि आप उपयोगकर्ता को पास करने के लिए पास करते हैं यदि आप उन्हें एक काम करते हैं।

ऑब्जेक्टिव-सी में, @interfaceआप अपने निजी सदस्यों को सूचीबद्ध करने के लिए मजबूर करते हैं (कम से कम, कार्यान्वयन फ़ाइल में निजी तरीके प्राप्त करने का एक तरीका है)।

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

क्यों? एनकैप्सुलेशन OOP का एक मुख्य सिद्धांत है, C ++ और Obj-C में इस मूल क्षमता की कमी क्यों है? क्या ओब्ज-सी या सी ++ के लिए किसी प्रकार का सर्वोत्तम कार्य है जो सभी कार्यान्वयन को छुपाता है?

धन्यवाद,


4
मै तुम्हारा दर्द समझ सकता हू। मैं सी ++ से चिल्लाता हुआ भाग गया जब मैंने पहली बार एक निजी क्षेत्र को एक कक्षा में जोड़ा और इसका इस्तेमाल करने वाली हर चीज को फिर से जोड़ना था।
लैरी कोलेमन

@Larry, मुझे इससे ज़्यादा ऐतराज नहीं है, लेकिन यह एक महान OO भाषा के रूप में हेरलडेड लगती है, लेकिन यह "ठीक से" भी अतिक्रमण नहीं कर सकती है।
स्टीफन फुरलानी

2
प्रचार पर विश्वास मत करो। स्थिर और गतिशील टाइपिंग कैंप दोनों में OO करने के बेहतर तरीके हैं।
लैरी कोलमैन

यह कुछ मायनों में एक शानदार भाषा है, लेकिन इसकी ओओ क्षमताओं की वजह से नहीं, जो सी पर 67 सिला का ग्राफ्टिंग कर रहे हैं
डेविड थॉर्नले

आपको कुछ C प्रोग्रामिंग करनी चाहिए। तब आपको इस बात की बेहतर समझ होगी कि ये भाषाएँ वे क्यों हैं, जिनमें जावा सी # आदि शामिल हैं
हेनरी

जवाबों:


6

सवाल यह है कि संकलक को यह जानना होगा कि कोई वस्तु कितनी बड़ी है। यदि ऐसा है, तो संकलक को उन्हें गिनने के लिए निजी सदस्यों के बारे में जानना होगा।

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

C ++ में, यह संभव है कि वस्तुओं का स्थानीय स्तर पर या ढेर पर प्रतिनिधित्व किया जाए। इसलिए, संकलक को यह जानना होगा कि कोई वस्तु कितनी बड़ी है, ताकि वह एक स्थानीय चर या सरणी को आवंटित कर सके।

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


संकलक इस जानकारी को प्राप्त करने के लिए ऑब्जेक्ट लाइब्रेरी को नहीं देख सकता है? यह जानकारी मानव-पठनीय के बजाय मशीन-पठनीय क्यों नहीं हो सकती है?
स्टीफन फुरलानी

@ स्टीफन: संकलन के समय, आवश्यक रूप से एक वस्तु पुस्तकालय नहीं है। चूंकि वस्तुओं का आकार संकलित कोड को प्रभावित करता है, इसलिए इसे संकलन समय पर जाना जाता है, न कि केवल लिंक समय पर। इसके अलावा, वर्ग ए को परिभाषित करने के लिए ए, बी को परिभाषित करना संभव है, और क्लास बी की वस्तुओं का उपयोग करने के लिए ए और एपीपी में फ़ंक्शन की परिभाषा। उस स्थिति में, ऑब्जेक्ट कोड से ऑब्जेक्ट का आकार लेते समय, A.cpp और B.cpp में से प्रत्येक को संकलित करना आवश्यक होगा।
डेविड थॉर्नले

संकलन के दौरान लिंक नहीं किया जा सकता है? मैं उस गहराई पर विवरण नहीं जानने के लिए कबूल करता हूं, लेकिन अगर कोई वस्तु का इंटरफ़ेस सामग्री को उजागर करता है, तो क्या उन सामग्रियों को लाइब्रेरी या अन्य मशीन-पठनीय घटक से उजागर नहीं किया जा सकता है? क्या उन्हें सार्वजनिक रूप से सुलभ हेडर फ़ाइल में परिभाषित किया जाना चाहिए ? मैं समझता हूँ कि इस सी भाषाओं के बहुमत का हिस्सा है, लेकिन यह करता है तो हो सकता है के लिए?
स्टीफन फुरलानी

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

14

C ++ के डिज़ाइन के कारण, स्टैक पर ऑब्जेक्ट बनाने के लिए कंपाइलर को पता होना चाहिए कि यह कितना बड़ा है। ऐसा करने के लिए हेडर फ़ाइल में सभी फ़ील्ड मौजूद होने चाहिए, क्योंकि यह सब वह है जो कंपाइलर हेडर को शामिल करते समय देख सकता है।

उदाहरण के लिए यदि आप एक वर्ग को परिभाषित करते हैं

class Foo {
    public int a;
    private int b;
};

तब sizeof(Foo)है sizeof(a) + sizeof(b)। यदि निजी क्षेत्रों को अलग करने के लिए कुछ तंत्र था, तो हेडर शामिल हो सकता है

class Foo {
    public int a;
};

के साथ sizeof(Foo) = sizeof(a) + ???

यदि आप वास्तव में निजी डेटा को छिपाना चाहते हैं, तो पिंपल मुहावरे का प्रयास करें

class FooImpl;
class Foo {
    private FooImpl* impl;
}

हेडर में और FooImplकेवल Foo'कार्यान्वयन फ़ाइल में एक परिभाषा ।


ओह। मुझे नहीं पता था कि यह मामला था। क्या इसीलिए जावा, सी #, और ओबज-सी जैसी भाषाओं में "क्लास ऑब्जेक्ट्स" हैं, ताकि वे क्लास से पूछ सकें कि ऑब्जेक्ट कितना बड़ा हो सकता है?
स्टीफन फुरलानी

4
एक निजी कार्यान्वयन के लिए एक पिंपल, एक सूचक का उपयोग करने का प्रयास करें। चूँकि सभी क्लास पॉइंटर्स समान आकार के होते हैं इसलिए आपको कार्यान्वयन क्लास को परिभाषित करने की आवश्यकता नहीं है, केवल इसे घोषित करें।
स्कॉट वेल्स

मुझे लगता है कि टिप्पणी के बजाय उत्तर होना चाहिए।
लैरी कोलेमन

1

यह सब डिजाइन की पसंद के अनुसार आता है।

यदि आप सी ++ या ऑब्जेक्टिव-सी क्लास के निजी कार्यान्वयन विवरणों को छिपाना चाहते हैं, तो आप या तो एक या एक से अधिक इंटरफेस प्रदान करते हैं, जो क्लास (सी ++ शुद्ध वर्चुअल क्लास, ऑब्जेक्टिव-सी @प्रोटोकॉल) और / या आप क्लास का समर्थन करते हैं। एक स्थिर कारखाना विधि या एक वर्ग कारखाना वस्तु प्रदान करके खुद का निर्माण करने में सक्षम।

हेडर फ़ाइल / क्लास डिक्लेरेशन / @ इंटरफ़ेस में प्राइवेट वेरिएबल्स के उजागर होने का कारण यह है कि आपकी क्लास के एक उपभोक्ता को इसका एक नया उदाहरण बनाने की आवश्यकता हो सकती है और क्लाइंट कोड में new MyClass()या यह [[MyClass alloc]init]समझने के लिए कंपाइलर की आवश्यकता है कि MyClass कितना बड़ा है आबंटन करने के लिए ऑब्जेक्ट है।

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

C ++ और Objective-C में, अतिरिक्त इंटरफ़ेस / @ प्रोटोकॉल फ़ाइल को लिखने और बनाए रखने की तुलना में हेडर फ़ाइल को सौंपना कम काम है। यह एक कारण है कि आप निजी कार्यान्वयन को इतनी बार उजागर करते देखते हैं।

C ++ में एक और कारण टेम्प्लेट है - कंपाइलर को प्रदान किए गए मापदंडों के लिए उस वर्ग के एक संस्करण को उत्पन्न करने के लिए कक्षा के विवरण को जानना होगा। कक्षा के सदस्यों का आकार परिमाणीकरण के साथ भिन्न होता है, इसलिए इसकी जानकारी होना आवश्यक है।

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