C ++ हेडर में "नेमस्पेस का उपयोग"


119

हमारे सभी सी ++ पाठ्यक्रमों में, सभी शिक्षक अपनी फाइलों में एस के using namespace std;बाद हमेशा सही डालते हैं । यह मुझे तब से खतरनाक लग रहा है जब तक कि किसी अन्य प्रोग्राम में उस हेडर को शामिल करने से मुझे अपने प्रोग्राम में आयात किए गए नेमस्पेस मिल जाएंगे, हो सकता है कि इसे साकार किए बिना, इरादा या इसे (हेडर इंक्लूजन बहुत गहरा नेस्टेड हो सकता है)।#include.h

इसलिए मेरा प्रश्न दोहरा है: क्या मैं सही हूं कि using namespaceइसे हेडर फ़ाइलों में उपयोग नहीं किया जाना चाहिए, और / या इसे इसे पूर्ववत करने का कोई तरीका है, कुछ इस प्रकार है:

//header.h
using namespace std {
.
.
.
}

इसी तर्ज पर एक और सवाल: क्या हेडर को #includeसभी हेडर को फाइल करना चाहिए जो कि इसी .cppफाइल की जरूरत है, केवल उन है कि हेडर परिभाषाओं के लिए आवश्यक हैं और .cppफाइल #includeको बाकी है, या कोई भी नहीं है और सब कुछ की घोषणा के रूप में की जरूरत है extern?
सवाल के पीछे तर्क ऊपर के रूप में ही है: मुझे आश्चर्य नहीं है जब .hफाइलें शामिल हैं।

इसके अलावा, अगर मैं सही हूं, तो क्या यह एक सामान्य गलती है? मेरा मतलब है कि वास्तविक दुनिया की प्रोग्रामिंग और "वास्तविक" परियोजनाओं में।

धन्यवाद।



3
साइड नोट के रूप में, यदि आपको using namespaceबयानों के कारण नाम टकराव मिलते हैं तो आप समस्या को हल करने के लिए पूरी तरह से योग्य नाम का उपयोग कर सकते हैं।
मारियस बंसीला

जवाबों:


115

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

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

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


2
क्या हम usingअपनी .cppफाइलों में स्टेटमेंट का उपयोग करने के लिए स्वतंत्र हैं ? 3rdPartyLib::BigClassName<3rdPartyLib::AnotherBigName,3rdPartyLib::AnotherBigName>::Iteratorरों उंगलियों को मौत।
क्रिस्टोफर

1
और हमें उन templateकार्यों को कैसे सुव्यवस्थित करना चाहिए - जो हेडर में होने चाहिए? typedefs?
क्रिस्टोफर

1
@donlan, ऐसा लगता है कि आपको कुछ समय के लिए कोई प्रतिक्रिया नहीं मिली ... हाँ, आप बहुत चिंता के बिना फाइलों के usingभीतर बयानों का उपयोग कर सकते हैं .cppक्योंकि गुंजाइश केवल उस फ़ाइल तक सीमित होगी, लेकिन एक #includeबयान से पहले ऐसा कभी नहीं करें । हेडर में परिभाषित टेम्प्लेट फ़ंक्शंस के लिए, दुर्भाग्य से मुझे नामस्थान लिखने के अलावा एक अच्छे समाधान का पता नहीं है ... शायद आप usingएक अलग दायरे में एक घोषणा रख सकते हैं { /* using statement in between brackets */ }, जो कम से कम इसे वर्तमान फ़ाइल से बचने से रोक देगा। ।
tjwrona1992

26

59 में सटर और अलेक्जेंड्रेस्कु के "C ++ कोडिंग मानक: 101 नियम, दिशानिर्देश और सर्वोत्तम अभ्यास" :

59. शीर्ष लेख फ़ाइल में या #include से पहले नाम स्थान का उपयोग न लिखें।

Namespace usingआपकी सुविधा के लिए है, न कि आपके लिए दूसरों पर भड़काने के लिए: कभी भी usingएक usingनिर्देश से पहले एक घोषणा या एक निर्देश न लिखें #include

कोरोलरी: हेडर फ़ाइलों में, नाम-स्तर के usingनिर्देश या usingघोषणाएँ न लिखें ; इसके बजाय, स्पष्ट रूप से नामस्थान-योग्य सभी नाम।

एक हेडर फ़ाइल एक या एक से अधिक स्रोत फ़ाइलों में एक अतिथि है। एक हेडर फ़ाइल जिसमें usingनिर्देश और घोषणाएँ शामिल हैं, अपने उपद्रवी मित्रों को भी ऊपर लाता है।

एक using घोषणा एक दोस्त में लाता है। एक using निर्देश नेमस्पेस में सभी मित्रों को लाता है। आपके शिक्षकों का उपयोग using namespace std;एक प्रत्यक्ष निर्देश है।

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


12

हेडर के अंदर हेडर शामिल करते समय आपको सावधान रहने की आवश्यकता है। बड़ी परियोजनाओं में, यह एक बहुत पेचीदा निर्भरता श्रृंखला बना सकता है जो वास्तव में आवश्यक होने की तुलना में बड़े / लंबे पुनर्निर्माण को ट्रिगर करता है। की जाँच करें इस लेख और अपने अनुवर्ती सी ++ परियोजनाओं में अच्छी शारीरिक संरचना के महत्व के बारे में अधिक जानने के।

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

नामस्थानों के लिए, मैं अपनी शीर्ष लेख फ़ाइलों में स्पष्ट नाम स्थान का उपयोग कर रहा हूं, और केवल using namespaceअपनी सीपीपी फाइलों में ही डाल सकता हूं।


1
आप कैसे templateकार्य घोषणा को सुव्यवस्थित करते हैं ? हैडर में घटित होना है, नहीं?
क्रिस्टोफर

6

गोडार्ड स्पेस फ्लाइट सेंटर कोडिंग मानकों (सी और सी ++ के लिए) देखें। यह होने की तुलना में थोड़ा कठिन हो जाता है - एसओ प्रश्नों के अद्यतन उत्तर देखें:

GSFC C ++ कोडिंग मानक कहता है:

§3.3.7 प्रत्येक हेडर फाइल को #includeउन फाइलों को संकलित करना होगा, जो उपयोगकर्ताओं को #includeआवश्यक फाइलों के लिए मजबूर करने के बजाय । #includesहेडर की जरूरत के लिए सीमित होना चाहिए; अन्य #includesको स्रोत फ़ाइल में रखा जाना चाहिए।

क्रॉस-संदर्भित प्रश्नों के पहले में अब GSFC C कोडिंग मानक, और तर्क से एक उद्धरण शामिल है, लेकिन पदार्थ समान है।


5

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

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


4

तुम सही हो। और किसी भी फ़ाइल में केवल उस फ़ाइल द्वारा आवश्यक हेडर शामिल होना चाहिए। के रूप में के लिए "वास्तविक दुनिया परियोजनाओं में चीजें गलत आम है?" - अरे हाँ!


4

प्रोग्रामिंग में सभी चीजों की तरह, व्यावहारिकता को डॉगमैटिज़्म, आईएमओ पर जीतना चाहिए।

जब तक आप निर्णय को विस्तृत करते हैं, तब तक ("हमारी परियोजना एसटीएल का बड़े पैमाने पर उपयोग करती है, और हम सब कुछ std ::" के साथ प्रस्तुत करना नहीं चाहते हैं), मैं इसके साथ समस्या नहीं देखता हूं। केवल एक चीज जो आप जोखिम में डाल रहे हैं, वह है नाम टक्कर, सब के बाद और एसटीएल की सर्वव्यापकता के साथ यह एक समस्या होने की संभावना नहीं है।

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


4

के संबंध में "क्या पूर्ववत करने का कोई तरीका है [एक usingघोषणा]?"

मुझे लगता है कि यह बताना उपयोगी है कि usingघोषणाएँ गुंजाइश से प्रभावित हैं।

#include <vector>

{   // begin a new scope with {
    using namespace std;
    vector myVector;  // std::vector is used
}   // end the scope with }

vector myOtherVector;   // error vector undefined
std::vector mySTDVector // no error std::vector is fully qualified

तो प्रभावी रूप से हाँ। के दायरे को सीमित करकेusingघोषणा इसका प्रभाव केवल उस दायरे के भीतर रहता है; जब यह गुंजाइश खत्म हो जाती है तो यह 'पूर्ववत' है।

जब usingघोषणा किसी अन्य दायरे के बाहर किसी फ़ाइल में घोषित की जाती है तो उसमें फ़ाइल-स्कोप होता है और उस फ़ाइल में सब कुछ प्रभावित होता है।

हेडर फ़ाइल के मामले में, यदि usingघोषणा फ़ाइल-स्कोप पर होती है , तो यह किसी भी फ़ाइल के दायरे तक विस्तारित हो जाएगा जिसमें हेडर शामिल है।


2
आपको केवल वही प्रतीत होता है कि वास्तविक प्रश्न को कैसे समझा गया ... हालाँकि, मेरा संकलन कक्षा मंदी के अंदर मेरे बारे में बहुत खुश नहीं है।
जंगपोपर

यह जवाब ओपी के विचार के साथ समस्या को समझाकर और भी बेहतर बनाया जा सकता है कि कैसे कार्य करना चाहिए (जैसे namespaceघोषणा सामग्री) बनाम यह वास्तव में कैसे काम करता है (एक चर की तरह)। {}इसे संलग्न करने के {}बाद इसका दायरा सीमित हो जाता है। यह एक आकस्मिक तरीका है जो using namespaceविश्व स्तर पर लागू होता है।
TafT

2

मेरा मानना ​​है कि यदि आप इस तरह से एक नेस्टेड नेमस्पेस में अपनी घोषणाएं लिखते हैं तो आप C ++ हेडर में सुरक्षित रूप से 'उपयोग' कर सकते हैं:

namespace DECLARATIONS_WITH_NAMESPACES_USED_INCLUDED
{
    /*using statements*/

    namespace DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED
    {
        /*declarations*/
    }
}

using namespace DECLARATIONS_WITH_NAMESPACES_USED_INCLUDED::DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED;

इसमें उपयोग किए गए नाम के बिना केवल 'DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED' में घोषित चीजें शामिल होनी चाहिए। मैंने इसे mingw64 कंपाइलर पर टेस्ट किया है।


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

हालांकि इस पैटर्न का एक दुर्भाग्यपूर्ण दुष्प्रभाव यह है कि अंतरतम नामस्थान के अंदर घोषित किसी भी वर्ग को कंपाइलर त्रुटि संदेशों में पूरी तरह से योग्य नाम के साथ दिखाई देगा error: ... DECLARATIONS_WITH_NAMESPACES_USED_INCLUDED:: DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED::ClassName ...:। कम से कम, कि यह मेरे लिए जी ++ में क्या हो रहा है।
एंथनी हॉल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.