2013-10-25 13 views
16

मैं केवल सी ++ (उदा। <cstdlib>) के लिए विशिष्ट शीर्षलेख फ़ाइलों का उपयोग कर रहा हूं, हालांकि मुझे अभी भी विश्व स्तर पर घोषित फ़ंक्शंस मिलते हैं, और न केवल std नामस्थान में कार्य करता है। क्या इसे रोकने के लिए कोई तरीका है, शायद एक कंपाइलर स्विच?std namespace के बाहर मानक कार्यों को रोकें

उदाहरण के लिए, निम्न कोड:

> g++ -c main.cpp main.o 
main.cpp: In function ‘float random()’: 
main.cpp:2:14: error: new declaration ‘float random()’ 
/usr/include/stdlib.h:327:17: error: ambiguates old declaration ‘long int random()’ 

या

> clang++ main.cpp -o main.o 
main.cpp:2:7: error: functions that differ only in their return type cannot be overloaded 
float random() { return 0.0f; } 
/usr/include/stdlib.h:327:17: note: previous declaration is here 
extern long int random (void) __THROW; 

जो कि stdlib.h के कारण होता है ":

#include <cstdlib> 
float random() { return 0.0f; } 
int main() { return 0; } 

निम्न त्रुटि के साथ लिनक्स के तहत संकलित करने के लिए, विफल प्रदूषित "वैश्विक नामस्थान अपने random समारोह के साथ।

नोट, कि विजुअल स्टूडियो का उपयोग करते हुए, विंडोज़ पर संकलन करते समय मुझे इन समस्याओं का सामना नहीं करना पड़ रहा है।

+1

ध्यान दें कि 'यादृच्छिक' ** सी मानक पुस्तकालय का हिस्सा नहीं है **। यह कहना नहीं है कि समस्या असली नहीं है। –

+0

@PeteBecker दरअसल, यह [POSIX से] आता है (http://pubs.opengroup.org/onlinepubs/9699919799/functions/random.html)। चीज़ों को भी लायक बनाता है, किसी को केवल सी मानक नामों के लिए ही नहीं देखना चाहिए, बल्कि सभी पॉज़िक्स सामानों के लिए भी देखना है। :( –

उत्तर

10
  1. <cstdlib> हमेशा एसटीडी नाम स्थान से स्थापित हो जाएगा, और कभी कभी, वैश्विक प्रतीकों को परिभाषित करते हुए <stdlib.h> हमेशा वैश्विक प्रतीक परिभाषित करेगा, और कभी कभी एसटीडी नाम स्थान पॉप्युलेट। यह क्रियान्वयन से कार्यान्वयन में भिन्न होता है।

  2. मानक लिखते हैं:

    Every C header, each of which has a name of the form name.h , behaves as if each name placed in the standard library namespace by the corresponding cname header is placed within the global namespace scope. It is unspecified whether these names are first declared or defined within namespace scope (3.3.6) of the namespace std and are then injected into the global namespace scope by explicit using-declarations (7.3.3).

    जिसका मतलब है, कि संकलक एक ही समय पर वैश्विक गुंजाइश और std नाम स्थान में उन प्रतीकों डाल करने के लिए अनुमति दी है।

  3. इसलिए, हम दूसरे पर एक हेडर फ़ाइल को प्राथमिकता देने के लिए कोई लाभ नहीं देखते हैं। क्योंकि वे दोनों वैश्विक दायरे को प्रदूषित करने की संभावना रखते हैं।

    हालांकि, यह अभी std नाम स्थान जब #include <cstdlib> उपयोग करने के लिए, और std जब #include <stdlib.h>, सुनिश्चित करें कि आपके कोड सभी संकलक कार्यान्वयन के लिए संकलन कर सकते हैं बनाने के लिए उपयोग नहीं करते हैं आवश्यक है।

  4. सलाह: मानक पुस्तकालयों में नामों का उपयोग न करें। सबसे पहले, उन्हें काम करने की गारंटी नहीं है। (नोट: #include <csomething> पर कुछ कंपाइलर कार्यान्वयन वास्तव में वैश्विक दायरे को साफ रखते हैं, इसलिए इस पर कभी भी निर्भर न करें।) दूसरा, यह कोड पाठकों और रखरखाव को भ्रमित कर देगा, क्योंकि लगभग हर कोई मान लेगा कि मानक नाम वास्तव में मानक हैं, इससे कोई फर्क नहीं पड़ता कि वे कहां से आए हैं ।

+2

बीटीडब्ल्यू, सी ++ 98 ने वैश्विक नामस्थान को प्रदूषित करने के लिए ' 'की अनुमति नहीं दी, सी ++ ने अनुमति की शुरुआत की क्योंकि बहुत से कार्यान्वयन में आवश्यकता को पूरा करने में कठिनाई थी (यदि आप नियंत्रण नहीं करते हैं तो यह करना बहुत कठिन या असंभव है सी लाइब्रेरी के साथ-साथ, मुझे उन कठिनाइयों का वर्णन करने वाले libstdC++ लोगों द्वारा एक पेपर याद रखना प्रतीत होता है, लेकिन मुझे अब यह नहीं मिला है)। – AProgrammer

6

घोषणा घोषणा टकराव को रोकने के लिए आप अपने कार्यों को अपने नामों में घोषित कर सकते हैं।

namespace MyFunc 
{ 
float random() { return 0.0f; } 
}; 
+0

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

0

आमतौर पर मैं अपने फ़ंक्शन नाम क्या एक मानक के रूप में परिभाषित किया गया से अलग रखना पसंद करेंगे। पूर्व में कोई व्यक्ति यादृच्छिक रूप से myRandom के रूप में फ़ंक्शन नाम का उपयोग कर सकता है ताकि मैं लोगों को सूचित कर सकूं, जो बाद में अपना कोड बनाए रखेंगे, कि फ़ंक्शन का उपयोग मानक के रूप में परिभाषित नहीं किया गया है।

2

मानक वैश्विक नामस्थान में सी मानक कार्यों के नाम लाने के लिए मानक <c???> हेडर स्पष्ट रूप से अनुमति देता है।

+3

मेरी राय में, वैश्विक नामस्थान में नाम डालने से पहले स्थान पर 'std' नेमस्पेस रखने के उद्देश्य को हराया जाता है। मुझे लगता है कि यह अनुमति पिछड़ा संगतता के लिए है। ध्यान दें कि मानक परमिट, लेकिन इसकी आवश्यकता नहीं है, इसलिए अभी भी एक स्विच हो सकता है जो इसे बंद कर देता है। – CygnusX1

+1

जो कुछ भी कारण है, मानक वह करता है जो मानक करता है, और इसके परिणामस्वरूप पोर्टेबल कोड में सी कार्यों के साथ नाम संघर्ष नहीं होना चाहिए। –

3

सामान्य रूप से आपको पहले स्थान पर पुनर्विक्रय से बचने की कोशिश करनी चाहिए। आप इसे नामस्थानों का उपयोग करके या अपने स्रोत को उन फ़ाइलों में विभाजित करके कर सकते हैं जिनमें cstdlib और अन्य शामिल हो सकते हैं जो आपके (नाम संघर्ष) फ़ंक्शन के static संस्करण का उपयोग कर सकते हैं।

यदि यह कोई विकल्प नहीं है तो पढ़ने पर जाएं। लेकिन ध्यान रखें कि निम्नलिखित बहुत ही मंच विशिष्ट हो सकते हैं।

बस अपना cstdlib और stdlib.h पर एक नज़र होने से यहाँ मेरे घर पर मैंने देखा एक स्विच है जिसके द्वारा cstdlib निर्णय लेता है तो यह stdlib.h शामिल या सिर्फ abort, atext और std नाम स्थान में exit वाणी नहीं है।

जाहिर है आप stdlib.h शाखा में खींचते हैं। इस फ़ाइल में आगे देखकर मैंने मैक्रो __BEGIN_NAMESPACE_STD और बाद में __END_NAMESPACE_STD पर ध्यान दिया। हो सकता है कि आप इसका इस्तेमाल कर सकें, लेकिन यह है (जैसा कि नाम बताता है) कुछ कार्यान्वयन आंतरिक मैक्रो और सीधे आपके द्वारा सेट नहीं किया जाना चाहिए। हालांकि, यह किसी कारण से होना चाहिए ताकि आप इसके लिए खोज के साथ भाग्य प्राप्त कर सकें।

कुछ और खोजों के बाद यह पता चला कि random कई कार्यों (और घोषणाओं) में से एक है जो __BEGIN_NAMESPACE_STD में लिपटे नहीं हैं। इसलिए, यह समस्या का समाधान नहीं है। (मुझे एक और मैक्रो _GLIBCPP_USE_NAMESPACES मिला जो आंतरिक रूप से #define __BEGIN_NAMESPACE_STD namespace std { पर भी उपयोग किया जाता है)।

तो इसे समेटने के लिए: यह कोई व्यवहार्य पथ नहीं है और आपको वर्णित वर्कअराउंड का उपयोग करना चाहिए।

+0

जबकि मैक्रो स्वयं आंतरिक है, शायद कुछ 'सार्वजनिक' कंपाइलर स्विच या कोई अन्य मैक्रो है जो इसे चालू कर सकता है? – CygnusX1

+0

मेरा विचार भी है लेकिन मैं ई अभी तक नहीं मिला (मैंने अपना जवाब लिखते समय खोजना शुरू कर दिया)। मैं यह भी गारंटी नहीं दे सकता कि सब कुछ अच्छी तरह से लपेटा गया है लेकिन पहली नज़र में यह आशाजनक लग रहा था। – Nobody

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