C ++ में "उपयोग" घोषणा की गुंजाइश क्या है?


100

मैं सी + + में ation st डिक्लेरेशन ’का इस्तेमाल करके एसडीडी :: स्ट्रिंग और एसटीडी :: वेक्टर को स्थानीय नेमस्पेस (गैरजरूरी टाइपिंग को बचाने के लिए इस्तेमाल कर रहा हूं।

using std::string;
using std::vector;

class Foo { /*...*/ };

इस घोषणा पर क्या गुंजाइश है? अगर मैं हेडर में ऐसा करता हूं, तो क्या यह हेडर में शामिल हर सीपीपी फाइल में घोषणाओं का उपयोग करके इन 'को' इंजेक्ट करेगा?


18
बस के मामले में यह अन्य उत्तरों से स्पष्ट नहीं है: - शामिल फ़ाइल (हैडर) में फ़ाइल स्कोप पर एक usingघोषणा (या usingनिर्देश) न करें ! जो हेडर के उपयोगकर्ताओं के लिए सिरदर्द पैदा करेगा।
माइकल बूर

वास्तव में, एक शीर्षलेख में एक usingघोषणा (एक निर्देश ) नहीं डालते हैं , यहां तक ​​कि एक नाम स्थान के भीतर भी! समस्याओं के कारणों के लिए एक नाम स्थान के भीतर घोषणा का उपयोग करने की गुंजाइश देखें ।
निल्स वॉन बर्थ

@ निल्सवोनर्थ: यह थोड़ा अधिक है। usingक्लास और फंक्शन स्कोप का उपयोग चर्चा की गई समस्या के बारे में सुरक्षित है।
सेबेस्टियन मच


आपको ADL C ++ लुकअप सुविधा के बारे में पढ़ने में रुचि हो सकती है ।
एलेक्सिस विल्के

जवाबों:


59

जब आप C ++ में हेडर फ़ाइल को #include करते हैं, तो यह हेडर फ़ाइल की पूरी सामग्री को उस स्थान पर रखता है जिसे आपने इसे स्रोत फ़ाइल में शामिल किया था। तो एक फ़ाइल जिसमें एक usingघोषणा usingशामिल है, उस शीर्षक फ़ाइल में शामिल प्रत्येक फ़ाइल के शीर्ष पर घोषणा को रखने का सटीक समान प्रभाव पड़ता है ।


51
... जो आमतौर पर एक बुरी बात है।
कैटस्कुल

17
लेकिन अगर आप usingघोषणा namespaceको उस नामस्थान के दायरे तक सीमित रखते हैं, तो यह आम तौर पर ठीक है (आपकी विशेष आवश्यकताओं और शैली पर सामान्य कैविट्स के साथ)।
शून्य

1
... लेकिन अगर आप किसी नेमस्पेस के अंदर का उपयोग करते हैं, तो सुनिश्चित करें कि आप ऐसा कुछ करने की कोशिश नहीं कर रहे हैं जो सामान्य रूप से एक बुरा विचार है, जैसे कि आप दूसरे के अंदर नाम स्थान Y के बाहर घोषित वर्ग विधियों को एनकैश नहीं कर सकते। नाम स्थान X, बस इसलिए आप स्थानीय रूप से नाम स्थान X का उपयोग कर सकते हैं। इसीलिए हमारे पास पहले स्थान पर नामस्थान :: रिसॉल्वर का उपयोग होता है। यदि इसकी टाइपिंग की एक बड़ी समस्या है, तो या तो एक मैक्रो (जो आसानी से कोड की बदबू आ सकती है) या बेहतर अभी तक, इसे अपने स्वयं के स्रोत में अलग कर दें। जहाँ आप केवल नामस्थान का उपयोग करेंगे।
ओसिरिसगोत्र

1
हालांकि यह और इसी तरह के उत्तर अच्छी सलाह हैं, वे सवाल का जवाब नहीं देते हैं।
एमिल कॉर्मियर

116

हेडर फ़ाइलों के बारे में कुछ खास नहीं है जो usingघोषणा को जारी रखेगा । संकलन शुरू होने से पहले यह एक सरल पाठ प्रतिस्थापन है।

आप एक usingघोषणा को एक दायरे तक सीमित कर सकते हैं :

void myFunction()
{
   using namespace std; // only applies to the function's scope
   vector<int> myVector;
}

12
मैंने कभी नहीं सोचा था कि मैं इसे एक फ़ंक्शन के अंदर उपयोग कर सकता हूं!
अगस्टिनो

1
मुझे सभी नामों का एक गुच्छा मिला है जिसका उपयोग एक "conglomerator" -Type फ़ाइल द्वारा किया जा रहा है, और gmock यूनिट-परीक्षण अतिरिक्त थकाऊ था क्योंकि प्रत्येक परीक्षण में एक विशिष्ट नाम स्थान से चीजों का उपयोग किया जाता था, और मुझे लगता था कि मुझे प्रत्येक और प्रत्येक चर को योग्य बनाना होगा। usingकिसी फ़ंक्शन के अंदर (या यहां तक ​​कि एक gtest TESTमैक्रो!) का उपयोग करना मेरे जीवन को इतना बेहतर बनाता है!
dwanderson 16

54

उपयोग कथन का दायरा इस बात पर निर्भर करता है कि वह कोड में कहाँ स्थित है:

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

5
मुझे लगा कि usingकक्षा के दायरे में एक बयान जोड़ना संभव नहीं है ...? मेरे पास ओपी के रूप में एक ही सवाल था क्योंकि मैं std::सभी जगह टाइपिंग से बचना चाहता था । मुझे ऐसी कक्षाएं मिलीं जिनमें स्मार्ट पॉइंटर्स के साथ बहुत सारे वैक्टर का उपयोग किया गया है और पांच चरित्र std::उपसर्ग बहुत अधिक लाइन की लंबाई जोड़ता है - जो मुझे लगता है कि खराब हो गया है। तो मैं सोच रहा था कि क्या usingकक्षा वाले नेमस्पेस के भीतर एक निर्देश ठीक था? (भले ही हेडर के भीतर।)
थोमथोम

5
क्या होगा अगर इसे एक के दायरे में रखा जाए namespace { ... }?
einpoklum

तो आप पूरी तरह से लिख सकते हैं: {नेमस्पेस ब्लाबला का उपयोग करना; कक्षा ब्लाह {}; } और वह प्रयोग केवल कक्षा के लिए लागू होगा?
दिनाज

8

गुंजाइश है जो भी घोषणा का उपयोग करने की गुंजाइश है।

अगर यह वैश्विक गुंजाइश है, तो यह वैश्विक दायरे में होगा। यदि यह हेडर फ़ाइल के वैश्विक दायरे में है, तो यह प्रत्येक स्रोत फ़ाइल के वैश्विक दायरे में होगा जिसमें हेडर शामिल है।

इसलिए, सामान्य सलाह है कि हेडर फ़ाइलों के वैश्विक दायरे में घोषणाओं का उपयोग करने से बचें


3
यह काफी मजबूत नहीं है। बदलें के साथ मत करो
मार्टिन यॉर्क

1
से बचने से मजबूत नहीं है। "अन्य कारों को मारने से बचें"
बॉबोबो

6

मामले में उद्धृत, फ़ाइल ("अनुवाद इकाई"), जिसका अर्थ है हाँ, प्रत्येक फ़ाइल जिसमें यह शामिल है।

आप क्लास के अंदर भी स्टेटमेंट का उपयोग कर सकते हैं, जिस स्थिति में, यह उस क्लास के लिए प्रभावी है।

आम तौर पर, यदि आपको शीर्ष लेख में एक नाम स्थान निर्दिष्ट करने की आवश्यकता है, तो यह आवश्यक है कि हर पहचानकर्ता को पूरी तरह से योग्य बनाया जाए।


ध्यान दें कि usingएक वर्ग में घोषणा एक कक्षा के बाहर की तरह व्यवहार नहीं करती है - जैसे कि आप इसका उपयोग कक्षा के दायरे में लाने के coutबजाय कर सकते हैं std::cout
जीरो

2

वह सही है। स्कोप वह मॉड्यूल है जो usingघोषणा का उपयोग करता है । यदि कोई हेडर फाइल जिसमें मॉड्यूल शामिल हैं using, में घोषणाएं होती हैं, तो उन घोषणाओं का दायरा उस मॉड्यूल के साथ-साथ किसी भी अन्य मॉड्यूल में होता है जिसमें समान हेडर शामिल होते हैं।


1

कुछ टिप्पणियां हैं जो "न" कहने पर अयोग्य हो जाती हैं। यह बहुत कठोर है, लेकिन आपको यह समझना होगा कि यह कब ठीक होगा।

लिखना using std::stringकभी ठीक नहीं होता। using ImplementationDetail::Fooअपने हेडर में लिखते हुए, जब वह हेडर इंप्लीमेंटेशन डिटेल का ऐलान करता है :: Foo ओके हो सकता है, अगर आपके डिस्क्रिपशन में यूज़ डिक्लेरेशन होता है तो मोरेसो। उदाहरण के लिए

namespace MyNS {
    namespace ImplementationDetail {
        int Foo;
    }
    using ImplementationDetail::Foo;
}

1
हेडर का उपयोगकर्ता तब लिख सकता हैMyNS::Foo
पीटर रीमर्स

एक बेहतर उदाहरण है using boost::posix_time::ptime। सुनिश्चित करें कि उपयोगकर्ता लिख ​​सकता है MyNS::ptimeलेकिन यह दुनिया का अंत नहीं है, और इस तरह के कार्यों के लिए सक्षम होने की सुविधा से ऑफसेट किया जा सकता है MyFunction(ptime a, ptime b)
शून्य

5
क्योंusing std::string ठीक है कभी नहीं? यहां तक ​​कि बहुत सारे std::उपसर्गों को बचाने के लिए आपके अपने नामस्थान में भी ?
थोमथोम

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