2017-02-22 21 views
14

मेरे भ्रम की स्थिति से आता है "सी ++ प्राइमर 5 वीं संस्करण" खंड 13.3 का उपयोग कर-घोषणा, पेज 518.समारोह छिपने और C++

बहुत सावधान पाठकों को आश्चर्य हो सकता क्यों swap अंदर using घोषणा के लिए घोषणाओं को छिपा नहीं करता HasPtrswap का संस्करण।

मैंने इसके संदर्भ को पढ़ने की कोशिश की लेकिन अभी भी समझ में नहीं आया। क्या कोई इसे थोड़ा सा समझा सकता है? धन्यवाद। प्रश्न का कोड नमूना यहां दिया गया है।

कक्षा Foo मान लें कि h नामक एक सदस्य है, जिसमें HasPtr टाइप किया गया है।

void swap(HasPtr &lhs, HasPtr &rhs) 
{...} 

void swap(Foo &lhs, Foo &rhs) 
{ 
    using std::swap; 
    swap(lhs.h, rhs.h); 
} 

क्यों HasPtr के लिए swap छुपी नहीं है जो जबकि using std::swap भीतरी दायरे में है बाहरी दायरे में घोषित किया जा रहा है? धन्यवाद।

+1

क्योंकि 'उपयोग' का उस –

उत्तर

10

क्योंकि using std::swap; मतलब यह नहीं है "अब से, हर 'स्वैप' std::swap का उपयोग करना चाहिए", लेकिन "वर्तमान क्षेत्र में std से swap के सभी भार के लाने"।

इस मामले में, प्रभाव वही है जैसे आपने फ़ंक्शन के अंदर using namespace std; लिखा था।

+0

पर कोई प्रभाव नहीं पड़ता है, मैं समझता हूं कि' उपयोग 'घोषणा' std' में 'स्वैप' पेश करती है, लेकिन यदि यह सामान्य फ़ंक्शन घोषणा के समान काम करती है, तो उसे बाहरी स्थान से नाम छिपाना चाहिए, न कि बस 'std' में नाम प्रस्तुत करता है। बीटीडब्ल्यू, http://stackoverflow.com/questions/32265938/c-using-declaration-and-function-overload का कहना है कि 'उपयोग' का उपयोग और निर्देश अलग हैं, जो मुझे उलझन में डाल देता है। धन्यवाद। – Sean

+1

और घोषणा और निर्देश * अलग हैं लेकिन जैसा कि मैंने लिखा है, * इस मामले में * प्रभाव वही है। – molbdnilo

+0

धन्यवाद। यदि 'एफ' चर थे, तो यह छिपा होना चाहिए, है ना? परिवर्तनीय और फ़ंक्शन की घोषणाओं में अलग-अलग छिपाने वाली नीतियां हैं? – Sean

0

प्रभावी सी ++ तीसरा संस्करण स्कॉट Meyers द्वारा (आइटम 24)

compilers कॉल स्वैप करने के लिए देखते हैं, वे आह्वान करने के लिए सही स्वैप के लिए खोज। सी ++ के नाम देखने नियम सुनिश्चित करें कि इस इस मामले में टी

वैश्विक क्षेत्र में या प्रकार के रूप में एक ही नाम स्थान में किसी भी टी विशिष्ट स्वैप मिलेगा और कोड के दूसरे खंड में, compilers एक के लिए देखो HasPtr स्वैप और यदि उन्हें यह नहीं मिलता है तो वे std में सामान्य संस्करण पर वापस आते हैं।

0

उपयोग घोषणा का मतलब सभी std :: स्वैप अधिभारों पर विचार करना है जैसे कि उन्हें फ़ंक्शन के समान नामस्थान में परिभाषित किया गया था। चूंकि उपयोग फ़ंक्शन किसी फ़ंक्शन बॉडी में दिखाई देता है, इसलिए इसका अस्थायी रूप से प्रभाव पड़ता है: उस दायरे में।

यह निम्न करने के लिए प्रभाव में समान होता है:

void swap(HasPtr &lhs, HasPtr &rhs) 
{...} 

void swap(int &lhs, int &rhs) { std::swap(lhs, rhs); } 
void swap(char &lhs, char &rhs) { std::swap(lhs, rhs); } 
// etc. for other std::swap overloads of common types 

void swap(Foo &lhs, Foo &rhs) 
{ 
    swap(lhs.h, rhs.h); 
    // the other overloads of swap go out of scope here. 
} 

अधिक भार का नियमित रूप से नियम यह सुनिश्चित करें कि पहले स्वैप एक कहा जाता हो जाता है। यह "स्वैप" नामक स्थानीय चर घोषित करने के विपरीत है, जो पहले अधिभार को छुपाएगा।

6

का उपयोग कर-घोषणाusing std::swap कार्यों आप HasPtr और Foo स्वैप करने के लिए घोषणा की है छिपा नहीं है। यह नाम swap नामित क्षेत्र में std नामस्थान बनाता है। इसके साथ, std::swap ओवरलोड रिज़ॉल्यूशन में भाग ले सकते हैं।

सी ++ 11 स्टैंडर्ड से:

7.3.3 घोषणा का उपयोग कर

1 एक का उपयोग कर-घोषणा कथात्मक क्षेत्र में एक नाम का परिचय जो का उपयोग कर-घोषणा में प्रकट होता है।

का उपयोग कर-घोषणा:

using typenameऑप्टनेस्टेड-नाम-विनिर्देशक अयोग्य-आईडी;
using ::अयोग्य-आईडी;

सदस्य एक का उपयोग कर-घोषणा में निर्दिष्ट नाम कथात्मक क्षेत्र में घोषित किया जाता है जो का उपयोग कर-घोषणा दिखाई देता हो। [नोट: केवल निर्दिष्ट नाम घोषित किया गया है; में एक गणना नाम निर्दिष्ट करते हुए घोषणा-घोषणामें घोषणाकर्ता के घोषित क्षेत्र का उपयोग करके अपने गणक घोषित नहीं करता है। अंत टिप्पणी] एक का उपयोग कर-घोषणा नाम एक निर्माता (3.4.3.1), यह परोक्ष कंस्ट्रक्टर्स का एक सेट कक्षा में वाणी हैं, जिसमें का उपयोग कर-घोषणा प्रकट होता है (12.9); अन्यथा में निर्दिष्ट नाम-घोषणा किसी अन्य इकाई के नाम के लिए समानार्थी है।

आपके मामले में, तुम हो:

void swap(Foo &lhs, Foo &rhs) 
{ 
    using std::swap; 
    swap(lhs.h, rhs.h); 
} 

using std::swap; घोषणा कथात्मक क्षेत्र में std नाम स्थान है, जो swap(Foo&, Foo&) समारोह का मुख्य भाग है से नाम swap परिचय देता है। वैश्विक नामस्थान से swap नाम फ़ंक्शन के शरीर में अभी भी पहुंच योग्य है।

यदि आपने जो पोस्ट किया है वह फ़ंक्शन की संपूर्णता है, तो आपको using std::swap घोषणा की आवश्यकता नहीं है। तुम बस के साथ मिल सकता है:

void swap(Foo &lhs, Foo &rhs) 
{ 
    swap(lhs.h, rhs.h); 
} 

swap(HasPtr &lhs, HasPtr &rhs) के बाद से समारोह से दिख रहा है।

अब, नीचे दिए गए उदाहरण को देखें।

struct Bar {}; 

void swap(Bar& lhs, Bar& rhs) 
{ 
} 

struct Foo 
{ 
    int a; 
    Bar b; 
}; 

void swap(Foo& lhs, Foo& rhs) 
{ 
    swap(lhs.a, rhs.a); // A problem 
    swap(lhs.b, rhs.b); 
} 

लाइन में चिह्नित A problem के बाद से वहाँ कोई समारोह swap नामित कि तर्क के रूप में प्रकार int& की दो वस्तुओं के साथ काम कर सकते हैं एक समस्या है। आप निम्न विधियों में से एक का उपयोग कर कि ठीक कर सकते हैं:

  1. उपयोग std::swap स्पष्ट रूप से।

    void swap(Foo& lhs, Foo& rhs) 
    { 
        std::swap(lhs.a, rhs.a); 
        swap(lhs.b, rhs.b); 
    } 
    
  2. समारोह में std::swap परिचय दें।

    void swap(Foo& lhs, Foo& rhs) 
    { 
        using std::swap; 
        swap(lhs.a, rhs.a); 
        swap(lhs.b, rhs.b); 
    } 
    
+3

"एक उपयोग-घोषणा कुछ भी छिपी नहीं है" - यह इस मामले में सरल अयोग्यता के लिए वैश्विक नामस्थान में घोषित 'स्वैप' को छुपाता है। हालांकि, 'स्वैप' अभी भी एडीएल द्वारा पाया गया है, क्योंकि 'हैसप्राटर' का संबंधित नामस्थान वैश्विक नामस्थान है। यदि वैश्विक 'स्वैप' के पैरामीटर थे, तो कहते हैं, 'int & 'और आपने इसे' int' 'के तर्कों के साथ बुलाया है (जिसमें कोई नामस्थान नहीं है, इसलिए एडीएल को कुछ भी नहीं मिला है), आप देखेंगे द्वारा छुपा हुआ छुपा उपयोग की घोषणा ('std' अधिभार कहा जाएगा, भले ही वैश्विक अधिभार एक बेहतर मिलान है)। – bogdan

+0

@bogdan, त्रुटि को इंगित करने के लिए धन्यवाद। मैं आपकी टिप्पणी में सबकुछ से सहमत हूं। –

+0

@bogdan मुझे आपका जवाब पसंद है, लेकिन चूंकि यह एक उत्तर के बजाय एक टिप्पणी है, इसलिए ... मैंने आपके लिए मतदान किया है। मैंने वीएस 2015 पर कोशिश की, और घोषणा-घोषणा समारोह को छुपाती है, यह तर्क है कि 'हैसप्राटर' दुनिया को बचाता है। 'हैस्प्रेट' को वैश्विक नामस्थान में परिभाषित किया गया है और इसलिए वैश्विक नेमस्पेस की खोज की गई है और 'हैस्प्र' के साथ 'स्वैप' पाया गया है। – Sean

0

वास्तव में, HasPtr के लिए swap जबकि भीतरी दायरे में using std::swap छिपा हुआ है, लेकिन इस मामले में आंतरिक दायरे में std::swap बाहरी दायरे में HasPtr के लिए swap के समान है।

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