2011-05-12 19 views
288
#include <iostream> 
#include <set> 

using namespace std; 

class StudentT { 

public: 
    int id; 
    string name; 
public: 
    StudentT(int _id, string _name) : id(_id), name(_name) { 
    } 
    int getId() { 
     return id; 
    } 
    string getName() { 
     return name; 
    } 
}; 

inline bool operator< (StudentT s1, StudentT s2) { 
    return s1.getId() < s2.getId(); 
} 

int main() { 

    set<StudentT> st; 
    StudentT s1(0, "Tom"); 
    StudentT s2(1, "Tim"); 
    st.insert(s1); 
    st.insert(s2); 
    set<StudentT> :: iterator itr; 
    for (itr = st.begin(); itr != st.end(); itr++) { 
     cout << itr->getId() << " " << itr->getName() << endl; 
    } 
    return 0; 
} 

लाइन में की 'इस' तर्क के रूप में xxx गुजर:त्रुटि: xxx छोड देता है क्वालिफायर

cout << itr->getId() << " " << itr->getName() << endl; 

यह एक त्रुटि दे कि:

../main.cpp:35: error: passing 'const StudentT' as 'this' argument of 'int StudentT::getId()' discards qualifiers

../main.cpp:35: error: passing 'const StudentT' as 'this' argument of 'std::string StudentT::getName()' discards qualifiers

क्या इस कोड के साथ गलत क्या है? धन्यवाद!

+11

आपके कोड स्निपेट में लाइन 35 कहां है? –

+56

मेरी इच्छा है कि जीसीसी इस त्रुटि संदेश में सुधार करेगी, उदा। "क्वालिफायर को छोड़ देता है" -> "ब्रेक कॉन्स शुद्धता" – jfritz42

+12

@ jfritz42: अगर यह 'अस्थिर' – PlasmaHH

उत्तर

338

std::set में ऑब्जेक्ट्स const StudentT के रूप में संग्रहीत हैं। तो जब आप getId() को const ऑब्जेक्ट के साथ कॉल करने का प्रयास करते हैं तो संकलक किसी समस्या का पता लगाता है, अर्थात् आप कॉन्स्ट ऑब्जेक्ट पर एक गैर-कॉन्स्ट सदस्य फ़ंक्शन को कॉल कर रहे हैं, जिसकी अनुमति नहीं है क्योंकि गैर-कॉन्स्ट सदस्य फ़ंक्शन ऑब्जेक्ट को संशोधित नहीं करने के लिए कोई वचन नहीं देते हैं; इसलिए संकलक सुरक्षित धारणा बनाने जा रहा है कि getId() ऑब्जेक्ट को संशोधित करने का प्रयास कर सकता है लेकिन साथ ही, यह भी नोटिस करता है कि ऑब्जेक्ट स्थिर है; इसलिए कॉन्स्ट ऑब्जेक्ट को संशोधित करने का कोई भी प्रयास एक त्रुटि होना चाहिए। इसलिए संकलक त्रुटि संदेश उत्पन्न करता है। ,

void f(const StudentT & s) 
{ 
    cout << s.getId(); //now okay, but error with your versions 
    cout << s.getName(); //now okay, but error with your versions 
} 

एक sidenote के रूप आप:

समाधान सरल है: कार्यों स्थिरांक बनाने के रूप में:

int getId() const { 
    return id; 
} 
string getName() const { 
    return name; 
} 

यह आवश्यक है क्योंकि अब आप के रूप में स्थिरांक वस्तुओं पर getId() और getName() कॉल कर सकते हैं operator< को लागू करना चाहिए:

inline bool operator< (const StudentT & s1, const StudentT & s2) 
{ 
    return s1.getId() < s2.getId(); 
} 

नोट पैरामीटर अब const संदर्भ हैं।

+1

इस तरह के एक स्पष्ट स्पष्टीकरण। धन्यवाद। लेकिन मुझे आपके अंतिम कोड स्निपेट के बारे में आश्चर्य है। फ़ंक्शन पैरामीटर में संदर्भ का उपयोग क्यों करें? 'स्टूडेंट टी एंड एस 1, कॉन्स स्टूडेंट टी एंड एस 2 '? –

+0

@ राफेलएडेल: आप अनावश्यक प्रतिलिपि से बचने के लिए संदर्भ का उपयोग करते हैं, और 'const' क्योंकि फ़ंक्शन को ऑब्जेक्ट को संशोधित करने की आवश्यकता नहीं है, इसलिए' const' संकलन-समय पर इसे लागू करता है। – Nawaz

62

सदस्य कार्यों उस वर्ग उदाहरण को संशोधित नहीं const के रूप में घोषित किया जाना चाहिए:

int getId() const { 
    return id; 
} 
string getName() const { 
    return name; 
} 

कभी भी आप देखते हैं, "क्वालिफायर को छोड़ देता है" इसके बारे में const या volatile बात कर रहा है।

+2

@Fred के बारे में नहीं सोचेंगे - क्या आपको लगता है कि क्लास इंस्टेंस को संशोधित नहीं करने वाले सदस्य फ़ंक्शंस में कॉन्स्ट मॉडिफायर जोड़ने की ज़रूरत है? क्या इस मामले में त्रुटि के लिए कोई अन्य कारण है? मुझे संदेह है क्योंकि अधिकांश गेटर्स में मैं लिखता हूं, मैं इसमें कॉन्स मॉडिफायर नहीं जोड़ता हूं। – Mahesh

+0

@Fred - http://ideone.com/WXr9z – Mahesh

+0

@ माहेश: हां, यह [कॉन्स शुद्धता] का हिस्सा है (http://www.parashift.com/c++-faq-lite/const-correctness.html)। मुझे यकीन नहीं है कि यहां से 'कॉन्स्ट' आ रहा है, लेकिन मुझे संदेह है कि 'सेट' इत्यादि से एक कॉन्स संदर्भ लौटा रहा है ताकि इंस्टेंस को बदलने से रोक सके और इस प्रकार सेट को अमान्य कर दिया जा सके। –

3

वास्तव में सी ++ मानक (अर्थात C++ 0x draft) का कहना है (उनका कहना है कि मेरे लिए के लिए & @Ben वोइट @Xeo को tnx):

23.2.4 Associative containers
5 For set and multiset the value type is the same as the key type. For map and multimap it is equal to pair. Keys in an associative container are immutable.
6 iterator of an associative container is of the bidirectional iterator category. For associative containers where the value type is the same as the key type, both iterator and const_iterator are constant iterators. It is unspecified whether or not iterator and const_iterator are the same type.

तो कुलपति ++ 2008 Dinkumware कार्यान्वयन दोषपूर्ण है।


पुराना जवाब:

आप क्योंकि एसटीडी set::iterator लिब के कुछ कार्यान्वयन में है कि त्रुटि मिली set::const_iterator के समान है।

उदाहरण libstdC++ (छ के साथ भेज दिया ++) यह (पूरे स्रोत कोड के लिए here देखें) है के लिए:

typedef typename _Rep_type::const_iterator   iterator; 
typedef typename _Rep_type::const_iterator   const_iterator; 

और SGI की docs इसे राज्यों:

iterator  Container Iterator used to iterate through a set. 
const_iterator Container Const iterator used to iterate through a set. (Iterator and const_iterator are the same type.) 

दूसरी ओर कुलपति पर ++ 2008 एक्सप्रेस शिकायत किए बिना आपके कोड को संकलित करता है कि आप set::iterator एस पर गैर कॉन्स्टेशन विधियों को कॉल कर रहे हैं।

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