C ++: Namespaces - हेडर और सोर्स फाइल्स का सही तरीके से उपयोग कैसे करें?


90

दो स्रोत फ़ाइलों की एक जोड़ी पर विचार करें: एक इंटरफ़ेस घोषणा फ़ाइल ( *.hया *.hpp) और इसके कार्यान्वयन फ़ाइल ( *.cpp)।

*.hफ़ाइल को निम्न की तरह होने दें :

namespace MyNamespace {
  class MyClass {
  public:
    int foo();
  };
}

मैंने स्रोत फ़ाइलों में नाम स्थान का उपयोग करने के लिए दो अलग-अलग प्रथाओं को देखा है:

*.cpp प्रैक्टिस दिखाना # 1:

#include "MyClass.h"
using namespace MyNamespace;

int MyClass::foo() { ... }

*.cpp अभ्यास दिखा रहा है # 2:

#include "MyClass.h"
namespace MyNamespace {

  int MyClass::foo() { ... }

}

मेरा प्रश्न: क्या इन दोनों प्रथाओं में कोई अंतर है और क्या एक दूसरे से बेहतर माना जाता है?


30
वहाँ भी विकल्प 3 है: बस हमें पूरा नाम, जैसे int MyNamespace::MyClass::foo() ...
बेंजामिन बैनियर

1
संभव डुप्लिकेट: stackoverflow.com/questions/7789163/…
डेविड

@ डुप्लिकेट नहीं। ये प्रश्न एक दूसरे के पूरक हैं। डेव द्वारा दिए गए लिंक को "इस भी पढ़ें ..." को इस प्रश्न के साथ जोड़ने की सिफारिश। मेरा प्रश्न नौसिखियों को सही शैली चुनने में मदद करेगा।
निकोले

संभावित डुप्लिकेट: stackoverflow.com/questions/8210935/…
Firedragon

जवाबों:


65

एक कोड पठनीयता के दृष्टिकोण से, संभवतः इस कारण से # 2 विधि का उपयोग करना मेरी राय में बेहतर है:

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


डेव ने आपकी टिप्पणी के लिए अपनी टिप्पणी से जुड़े प्रश्न में अंतर के कुछ प्रमुख बिंदुओं (यदि कोई हो) को दो तरीकों के बीच में देखा है
दान एफ

दोस्तों, मैं वास्तव में नहीं जानता कि किसका चयन करना है। एक-दूसरे के पूरक होते हुए भी उनके पास प्रतिच्छेदन है।
निकोले

केवल यह स्वीकार करने के लिए टिप्पणी करना कि कुछ IDE जैसे CLion केवल क्रियान्वयन का पता लगाएगा यदि आप विकल्प / अभ्यास # 2 का उपयोग करते हैं।
पीडोस्ट्रॉनाका

@PedroTanaka क्या यह अभी भी मामला है? मैंने ऐसी किसी समस्या पर ध्यान नहीं दिया है।
जॉन मैकफर्लेन

@JMcF जब से मैंने टिप्पणी प्रकाशित की है, तब से मैंने जाँच नहीं की है। Clion के शुरुआती संस्करणों में समस्या हुई।
पेड्रोस्तानका

52

सबसे स्पष्ट वह विकल्प है जो आपने नहीं दिखाया:

int MyNamespace::MyClass::foo()
{
    //  ...
}

यह भी बहुत क्रिया है; ज्यादातर लोगों के लिए बहुत ज्यादा। चूंकि using namespaceनाम संघर्ष के लिए एक रसीद है, कम से कम मेरे अनुभव में, और बहुत सीमित दायरे और स्थानों को छोड़कर बचा जाना चाहिए, मैं आमतौर पर आपके # 2 का उपयोग करता हूं।


4
बहुत स्पष्ट धन्यवाद। साथ में हमने नेमस्पेस उपयोगकर्ताओं के लिए एक अच्छा FAQ पृष्ठ बनाया। :)
निकोले

2
दोस्तों, मैं वास्तव में नहीं जानता कि किसका चयन करना है। एक-दूसरे के पूरक होते हुए भी उनके पास प्रतिच्छेदन है।
निकोले

10

क्या इन दोनों प्रथाओं में कोई अंतर है

हाँ। # 1 और # 2 क्रमशः एक प्रयोग-निर्देश और एक नेमस्पेस परिभाषा के उदाहरण हैं। वे इस मामले में प्रभावी रूप से समान हैं लेकिन अन्य परिणाम हैं। उदाहरण के लिए, यदि आप एक नए पहचानकर्ता का परिचय देते हैं, तो MyClass::fooइसका एक अलग दायरा होगा:

# 1:

using namespace MyNamespace;
int x;  // defines ::x

# 2:

namespace MyNamespace {
  int x;  // defines MyNamespace::x
}

क्या एक को दूसरे से बेहतर माना जाता है?

# 1 पेशेवरों: थोड़ा और अधिक; मुश्किल से MyNamespaceअनजाने में कुछ परिचय । विपक्ष: मौजूदा पहचानकर्ताओं में अनायास ही खींच सकता है।

# 2 पेशेवरों: अधिक स्पष्ट है कि मौजूदा पहचानकर्ताओं और नई पहचानकर्ताओं की घोषणाओं की परिभाषाएँ दोनों से संबंधित हैं MyNamespace। विपक्ष: अनायास ही पहचानकर्ताओं को पेश करना आसान हो जाता है MyNamespace

# 1 और # 2 दोनों की आलोचना यह है कि वे एक संपूर्ण नामस्थान का उल्लेख कर रहे हैं, जब आप केवल सदस्यों की परिभाषा के बारे में परवाह करते हैं MyNamespace::MyClass। यह भारी-भरकम है और यह खराब इरादे का संचार करता है।

# 1 का एक संभावित विकल्प एक प्रयोग-घोषणा है जिसमें केवल उस पहचानकर्ता को शामिल किया जाता है जिसमें आप रुचि रखते हैं:

#include "MyClass.h"
using MyNamespace::MyClass;

int MyClass::foo() { ... }

5

मैं यह भी जोड़ना चाहूंगा कि यदि आप किसी कारण के कारण किसी cpp फ़ाइल में टेम्पलेट विशेषज्ञता को लागू करने का निर्णय लेते हैं और using namespaceआप पर भरोसा करते हैं तो आप निम्नलिखित समस्या में भाग लेंगे:

// .h file
namespace someNameSpace
{
  template<typename T>
    class Demo
    {
      void foo();
    };
}

// .cpp file
using namespace someNameSpace;

template<typename T>
void Demo<T>::foo(){}

// this will produce
// error: specialization of 'template<class T> void someNameSpace::Demo<T>::foo()' in different namespace [-fpermissive]
template<>
void Demo<int>::foo(){}

अन्यथा यदि आप # 2 विधि लागू करते हैं तो यह ठीक होगा।


0

मैं एक और तरीका जोड़ना चाहता हूँ, प्रयोग-घोषणा का उपयोग करके :

#include "MyClass.h"
using MyNamespace::MyClass;

int MyClass::foo() { ... }

अगर क्लास में कई फंक्शन्स हैं तो यह आपको कई बार नेमस्पेस नाम टाइप करने से बचाता है

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