2010-04-01 14 views
11

कुछ ऐसा कर दिया गया है मुझे थोड़ी देर के लिए परेशान कर रहा:क्या प्रत्येक वर्ग का अपना नामस्थान होना चाहिए?

वर्तमान ज्ञान है कि प्रकार एक namespace है कि केवल कार्य करता है जो प्रकार की गैर-सदस्य इंटरफ़ेस का हिस्सा है शामिल हैं में रखा जाना चाहिए है (देखें सी ++ कोडिंग मानक एडीएल को असंबंधित परिभाषाओं में खींचने से रोकने के लिए सटर और अलेक्जेंड्रेस्कु या here)।

क्या यह दर्शाता है कि सभी कक्षाओं के पास अपना नामस्थान होना चाहिए? यदि हम मानते हैं कि गैर-सदस्य फ़ंक्शंस के अतिरिक्त भविष्य में एक वर्ग को बढ़ाया जा सकता है, तो यह दो प्रकारों को समान नामस्थान में रखने के लिए सुरक्षित नहीं हो सकता है क्योंकि उनमें से कोई भी गैर-सदस्य फ़ंक्शन पेश कर सकता है जो दूसरे के साथ हस्तक्षेप कर सकता है।

कारण मैं पूछता हूं कि नामस्थान मेरे लिए बोझिल हो रहे हैं। मैं एक हेडर-केवल लाइब्रेरी लिख रहा हूं और मुझे अपने आप को कक्षा नामों का उपयोग करना पड़ता है जैसे कि प्रोजेक्ट :: घटक :: class_name :: class_name। उनके कार्यान्वयन सहायक कार्यों को कॉल करते हैं लेकिन चूंकि ये एक ही नामस्थान में नहीं हो सकते हैं, उनके पास भी पूरी तरह से योग्यता प्राप्त करने के लिए है!

संपादित करें:

कई जवाब सुझाव दिया है कि सी ++ नामस्थान बस नाम संघर्ष से बचने के लिए एक तंत्र है। ऐसा नहीं है। पैरामीटर लेने वाले सी ++ फ़ंक्शंस में Argument Dependent Lookup का उपयोग करके हल किया गया है। इसका अर्थ यह है कि जब संकलक फ़ंक्शन नाम से मेल खाने वाली फ़ंक्शन परिभाषा को खोजने का प्रयास करता है तो यह को उसी पैरास्पेस (ओं) के प्रत्येक पैरामीटर को उम्मीदवारों को ढूंढते समय के रूप में देखेगा।

इसमें A Modest Proposal: Fixing ADL में विस्तृत के रूप में अनपेक्षित, अप्रिय परिणाम हो सकते हैं। सटर और अलेक्जेंड्रेस्कू के नियमों ने कभी भी एक ही नामस्थान में एक वर्ग के रूप में कार्य नहीं किया जब तक कि वह उस वर्ग के इंटरफ़ेस का हिस्सा न हो। मैं नहीं देखता कि मैं उस नियम का पालन कैसे कर सकता हूं जब तक कि मैं प्रत्येक वर्ग को अपना नामस्थान देने के लिए तैयार नहीं हूं।

अधिक सुझाव बहुत स्वागत है!

+2

"उनके कार्यान्वयन कॉल सहायक कार्यों [कि] को पूरी तरह से योग्यता प्राप्त करनी है" - आप फंक्शन बॉडी के अंदर 'उपयोग' घोषणा या निर्देश डाल सकते हैं, अगर यह बिल्कुल मदद करता है। –

+4

सभी चीजों के प्यार के लिए पवित्र, कक्षाओं और नामस्थानों के बीच 1: 1 अनुपात लागू न करें। नामस्थान रखने के पूरे उद्देश्य को हरा देता है, और बहुत अधिक उंगली-काम की ओर जाता है। –

+3

@ जेम्स डी: मैं असहमत हूं। मुझे लगता है कि यह बहुत दूर नहीं जाता है। हमें यह सुनिश्चित करने की भी आवश्यकता है कि प्रत्येक नेमस्पेस स्वयं नामस्थान में है। –

उत्तर

7

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

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

0

शायद नहीं। Eric Lippert's post on the subject देखें।

युगल यहाँ बातें:

  1. एरिक Lippert एक सी # डिजाइनर है, लेकिन यहाँ वह क्या बुरा श्रेणीबद्ध डिजाइन के बारे में कह रहा है लागू होता है।
  2. उस लेख में वर्णित बहुत से कुछ को आपकी कक्षा को नामकरण के साथ सी # में नामस्थान के समान नाम देना है, लेकिन कई त्रुटियां सी ++ पर लागू होती हैं।

आप typedef एस का उपयोग करके कुछ टाइपिफ़ दर्द पर बचा सकते हैं लेकिन यह निश्चित रूप से केवल एक बैंड-सहायता है।

+1

एरिक लिपर्ट की सलाह सी # के लिए बहुत अच्छी है, और हो सकता है कि सामान्य रूप से .NET, लेकिन यह वास्तव में सी ++ पर लागू नहीं होता है क्योंकि सी ++ नामस्थान समान कार्य नहीं करते हैं। * गैर-वर्ग * कार्यों को अस्पष्ट होने से रोकने के लिए इस मामले में सी ++ नेमस्पेस की आवश्यकता है। – Gabe

+0

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

15

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

इसे और अधिक ठोस बनाने के लिए, मुझे उदाहरण के रूप में आदरणीय Boost C++ Libraries का उपयोग करने दें। बूस्ट के भीतर सभी तत्व boost:: में रहते हैं। बूस्ट के भीतर कुछ मॉड्यूल हैं, जैसे कि इंटरप्रोसेस लाइब्रेरी जिसमें boost::interprocess:: जैसे अपना नामस्थान है, लेकिन अधिकांश भाग के लिए, बूस्ट के तत्व (विशेष रूप से बहुत बार और मॉड्यूल में उपयोग किए जाने वाले तत्व) बस boost:: में रहते हैं। यदि आप बूस्ट के भीतर देखते हैं, तो यह दिए गए नेमस्पेस के कार्यान्वयन विवरण संग्रहीत करने के लिए अक्सर boost::detail या boost::name_of_module::detail का उपयोग करता है। मेरा सुझाव है कि आप इस तरह से अपने नामस्थान मॉडल।

+0

+1 "नहीं" के लिए +1 हालांकि मेरे पास प्रति पुस्तकालय नहीं होगा - लाइब्रेरी एक कार्यान्वयन इकाई है। एक नामस्थान आमतौर पर टीमों/परियोजनाओं/उप परियोजनाओं के साथ करना है। आपके पास एक नामस्थान हो सकता है जो 2 libs और exe – pm100

+1

@ pm100, हाँ, यदि आपके पास एक बहु-मॉड्यूल प्रोजेक्ट (एकाधिक पुस्तकालयों या अन्य लॉजिकल इकाइयों वाला एक) है, तो आप उन्हें सामूहिक रूप से एक नामस्थान के तहत एकजुट कर सकते हैं, लेकिन फिर मैं प्रति पुस्तकालय एक नामस्थान के साथ आंतरिक रूप से subdividing का सुझाव दिया जाएगा। –

8

नहीं, नहीं और एक हजार बार नहीं! सी ++ में नेमस्पेस वास्तुकला या डिजाइन तत्व नहीं हैं। वे नाम संघर्ष को रोकने के लिए बस एक तंत्र हैं। यदि अभ्यास में आपके पास नाम संघर्ष नहीं हैं, तो आपको नामस्थानों की आवश्यकता नहीं है।

+0

एक हजार और एक बार नहीं। –

+4

"वे नाम संघर्ष को रोकने के लिए बस एक तंत्र हैं।" असत्य। नामस्थान एडीएल को निर्देशित करने के लिए भी हैं। वैसे भी वे "के लिए" क्या हैं जो वास्तव में * करते हैं उससे कहीं कम महत्वपूर्ण है, अगर वे कुछ विशेष मामलों में अवांछनीय हैं। –

+2

नेमस्पेस ठीक * नहीं * एक साधारण नामकरण तंत्र हैं! Argument आश्रित लुकअप के साथ (http://en.wikipedia.org/wiki/Argument_dependent_name_lookup) कक्षा के समान नामस्थान में प्रत्येक फ़ंक्शन को उम्मीदवार माना जाता है जब कक्षा का एक वस्तु उपयोग किया जाता है। इसलिए सटर और अलेक्जेंड्रेस्कू का शासन। – thehouse

0

यह काफी दिलचस्प पेपर है, लेकिन फिर लेखकों को दिया गया कि यह एक अच्छा मौका था। ,

  • typedef क्योंकि वे केवल एक उपनाम और नहीं एक नए प्रकार
  • टेम्पलेट्स

परिचय तो मुझे क्या करना: हालांकि, मैं ध्यान दें कि समस्या ज्यादातर चिंताओं

namespace foo 
{ 
    class Bar; 

    void copy(const Bar&, Bar&, std::string); 
} 

और इसे आमंत्रित करें:

#include <algorithms> 

#include "foo/bar.h" 

int main(int argc, char* argv[]) 
{ 
    Bar source; Bar dest; 
    std::string parameter; 
    copy(source, dest, parameter); 
} 

फिर इसे foo::copy चुनना चाहिए। वास्तव में यह foo::copy और std::copy दोनों पर विचार करेगा लेकिन foo::copy टेम्पलेट नहीं होने पर प्राथमिकता दी जाएगी।

+0

कंपाइलर एक सामान्य काम को खुशी से चुना जाएगा यदि यह गैर-जेनेरिक से बेहतर मिलान है। आपके मामले में आप ठीक हैं, लेकिन इसलिए नहीं क्योंकि 'foo :: copy' एक टेम्पलेट नहीं है, लेकिन' std :: copy' की अनुमति देने के कारण एक अस्पष्ट कॉल होगा। यदि 'पैरामीटर' कहा गया था, तो एक स्ट्रिंग शाब्दिक, 'std :: copy' चुना गया होगा, क्योंकि यह सीधे इस तरह के मान को स्वीकार कर सकता है, जबकि' foo :: copy' को रूपांतरण की आवश्यकता होगी। –

+0

असल में, 'पैरामीटर' स्ट्रिंग अक्षरशः बनाकर, 'std :: copy' अब नहीं माना जाएगा, इसलिए आप अभी भी ठीक हैं। लेकिन सामान्य बिंदु खड़ा है। –

+0

बिल्कुल, मैं रूपांतरणों के बारे में बिंदु का उल्लेख करना भूल गया। –

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