2009-02-23 14 views
13

मैंने कई वर्षों तक सी ++ में प्रोग्राम किया है और मुझे अभी भी एक चीज़ के बारे में संदेह है। अन्य लोगों को कोड में कई स्थानों में मैं की तरह कुछ देखें:क्या इसका उपयोग करने का कोई कारण है->

void Classx::memberfunction() 
{ 
    this->doSomething(); 
} 

अगर मैं आयात/कि कोड का उपयोग करने की जरूरत है, मैं बस इस-> हिस्से को हटाने, और मैं कुछ भी टूटी हुई है या कुछ होने कभी नहीं देखा है दुष्प्रभाव।

void Classx::memberfunction() 
{ 
    doSomething(); 
} 

तो, क्या आप इस तरह के निर्माण का उपयोग करने के किसी भी कारण से जानते हैं?

संपादित करें: कृपया ध्यान दें कि मैं सदस्य कार्यों के बारे में बात कर रहा हूं, चर नहीं। मैं समझता हूं कि जब आप किसी सदस्य चर और फ़ंक्शन पैरामीटर के बीच अंतर बनाना चाहते हैं तो इसका उपयोग किया जा सकता है।

संपादित करें: स्पष्ट डुप्लिकेट: Are there any reasons not to use "this" ("Self", "Me", ...)?

उत्तर

8

गारंटी देने के लिए कि यदि आप एक मैक्रो है जो आपके सदस्य फ़ंक्शन के समान नाम से परिभाषित किया जा सकता है और आप निश्चित नहीं हैं कि यह विश्वसनीय रूप से अपरिभाषित है तो आप निश्चित नहीं हैं।

कोई मजाक नहीं, मुझे पूरा यकीन है कि मुझे इस कारण से बिल्कुल ठीक करना पड़ा!

+3

कोई भी इस बात का जिक्र नहीं कर रहा है कि सदस्य नामों को हल करने का एक और तरीका है http://en.wikipedia.org/wiki/Scope_resolution_operator का उपयोग करके। जैसे Classx :: DoSomething(); –

+7

यदि किसी फ़ंक्शन पर लागू होता है तो यह गारंटी देने का प्रभाव होता है कि संभवतः वर्चुअल फ़ंक्शन का कौन सा संस्करण लागू होता है, पॉलिमॉर्फिज्म को रोकता है और आमतौर पर ओवरडिन फ़ंक्शन के माता-पिता को कॉल करने के लिए उपयोग किया जाता है। यह इस के बराबर सुरक्षित नहीं है-> कुछ करना()। –

+1

यह सच है, मैं इस मामले के बारे में भूल गया था! धन्यवाद एंडी। –

2

मैं जब आप चीजों को स्पष्ट करने के लिए अतिरिक्त कोष्ठक का उपयोग की तरह पठनीयता के बारे में सोच सकते हैं।

1

मुझे नहीं लगता कि यह कंपाइलर में एक फर्क पड़ता है, लेकिन मैं हमेशा यह लिखता हूं-> क्योंकि मेरा मानना ​​है कि यह कोड स्वयं-दस्तावेज बनाता है।

2

मुझे लगता है कि यह मुख्य रूप से पाठक की सहायता के रूप में है। यह स्पष्ट करता है कि जिसे कहा जा रहा है वह वस्तु पर एक विधि है, न कि सामान्य कार्य। कोड पढ़ने पर, यह जानकर सहायक हो सकता है कि बुलाया गया फ़ंक्शन वर्तमान ऑब्जेक्ट में फ़ील्ड को बदल सकता है, उदाहरण के लिए।

25

यदि एक ही नाम के साथ एक ही दायरे में एक और चर है, तो यह-> अस्पष्टता को हटा देगा।

void Bar::setFoo(int foo) 
{ 
    this->foo = foo; 
} 

यह भी स्पष्ट करता है कि आप सदस्य चर/फ़ंक्शन को प्रतिबिंबित कर रहे हैं।

+0

इस तरह इसका उपयोग करने से यह मेरी राय में खराब नामकरण सम्मेलन के लिए बैंड-सहायता बनाता है। यह कोड को अनावश्यक रूप से अव्यवस्थित करता है। –

+4

बस सवाल का जवाब दें। – drby

+0

मैंने चर के बारे में कोई सवाल नहीं पूछा, यह एक ज्ञात मुद्दा है। मैंने सदस्य कार्यों के बारे में पूछा। –

1

असंबद्धता: यदि आपके पास एक ही नामस्थान में एक और समान नामकरण फ़ंक्शन/चर है? मैंने किसी अन्य कारण के लिए कभी भी उपयोग नहीं देखा है।

1

यह आपकी अपनी पसंद है। जब आप इसका इस्तेमाल करते हैं तो मुझे यह और अधिक स्पष्ट लगता है। लेकिन अगर आपको यह पसंद नहीं है, तो आप इसे छोड़ सकते हैं।

4

के रूप में "कोड कारण", एक सदस्य से एक स्थानीय पैरामीटर या मूल्य भेद करने के लिए (जो पहले हो सकती है):

class Foo 
{ 
    int member; 
    void SetMember(int member) 
    { 
     this->member = member; 
    } 
} 

हालांकि, कि बुरा practive के साथ शुरू है, और आमतौर पर स्थानीय स्तर पर हल किया जा सकता।

दूसरा कारण अधिक "पर्यावरण" है: यह कभी-कभी इंटेलिजेंस को फ़िल्टर करने में मदद करता है जिसे मैं वास्तव में ढूंढ रहा हूं। हालांकि, मैं यह भी बात करता हूं जब मैं उस सदस्य को ढूंढने के लिए इसका उपयोग करता हूं जिसे मैं ढूंढ रहा हूं, मुझे इसे भी हटा देना चाहिए।

तो हाँ, अच्छे कारण हैं, लेकिन वे सभी अस्थायी (और लंबे समय तक खराब) हैं।

+2

मैं असहमत हूं कि यह एक बुरा अभ्यास है। यदि आपके पास ऑब्जेक्ट या वेरिएबल के लिए अच्छा, स्पष्ट और स्पष्ट नाम है ... इसे क्यों बदलें? –

+0

आईएमओ कोडिंग मानक सार्वजनिक गुण बनाम आंतरिक सदस्यों बनाम स्थानीय चर/पैरामीटर unambigous बनाना चाहिए। जितना ज्यादा मैं टाइपिंग 'm_' से नफरत करता हूं, इसके लिए एक अच्छा कारण है। – peterchen

+0

स्पष्टीकरण के लिए: मुझे लगता है कि ऐसा होने पर यह ठीक है, लेकिन जब ऐसा होता है, तो संभवतः आपके पास पठनीयता की समस्या होती है और ध्यान पर्ची कीड़े के लिए आमंत्रण होता है। अब, आपका मानक 'इस->' को हमेशा 'विशिष्ट' के रूप में उपयोग करने के लिए घोषित कर सकता है, लेकिन मुझे नहीं लगता कि यह एक अच्छा विकल्प है। – peterchen

2

यह वास्तव में शैली का विषय है और जावा और सी # जैसी कई अन्य भाषाओं पर लागू होता है। कुछ लोग स्पष्ट this (या self, या Me, या जो कुछ भी) देखना पसंद करते हैं। बस अपने स्टाइल दिशानिर्देशों में जो कुछ भी है, उसके साथ जाएं, और यदि यह आपकी परियोजना है, तो आप दिशानिर्देशों का निर्णय लेते हैं।

+0

और कुछ भाषाएं (PHP, पायथन) इसे भी लागू करती हैं। उनमें से एक ओओ करने से नफरत करने के कारणों में से एक। –

1

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

2

इस तथ्य यह है कि चर इस्तेमाल किया जा रहा एक सदस्य चर के रूप में एक स्थानीय या वैश्विक चर करने का विरोध किया है के बारे में स्पष्ट होना करने के लिए किया जाता है:

यहाँ अपने ही सवाल है। ज्यादातर मामलों में यह जरूरी नहीं है, लेकिन दायरे के बारे में स्पष्ट होने पर सहायक हो सकता है यदि आपने एक ही नाम की घोषणा को कड़े दायरे में घोषित कर दिया है।

जिन कंपनियों पर मैंने काम किया है, हमने अभी सदस्य चर के लिए "m_" तैयार किया है। यह कभी-कभी सहायक हो सकता है, और मैं इसे "this->" का उपयोग करने के लिए बहुत पसंद करता हूं।

संपादित करें: the GCC docs पर एक लिंक जोड़ना, जो इस मामले का उपयोग करते हुए एक मामले को समझाता है-> गैर-निर्भर लुकअप को सही तरीके से काम करने के लिए आवश्यक है।

35

केवल जगह है जहाँ यह वास्तव में एक अंतर व्युत्पन्न वर्ग में टेम्पलेट्स में है बनाता है:

कारण details in the name lookup in C++ compilers को
template<typename T> 
class A { 
protected: 
    T x; 
}; 

template<typename T> 
class B : A<T> { 
public: 
    T get() { 
    return this->x; 
    } 
}; 

, यह स्पष्ट रूप से स्पष्ट कर दिया जाना नहीं है x एक (विरासत में मिला है) वर्ग के सदस्य है, this->x के साथ सबसे आसानी से किया जाता है। लेकिन यह एक गूढ़ मामला है, यदि आपके पास श्रेणीबद्ध श्रेणी पदानुक्रम नहीं हैं, तो आपको कक्षा के सदस्यों तक पहुंचने के लिए वास्तव में this का स्पष्ट रूप से उपयोग करने की आवश्यकता नहीं है।

1

मुझे सटीक परिस्थितियों में काफी याद नहीं आ रहा है, लेकिन मैंने देखा है (बहुत दुर्लभ) उदाहरण जहां मुझे जीसीसी के साथ कोड को सफलतापूर्वक संकलित करने के लिए "यह-> सदस्य नाम" लिखना पड़ा। मुझे याद है कि यह अस्पष्टता के संबंध में नहीं था और इसलिए समाधान को समझने में मुझे कुछ समय लगा। विजुअल स्टूडियो में इसका उपयोग किए बिना एक ही कोड संकलित किया गया।

+0

इसे निर्भर टेम्पलेट पैरामीटर के साथ करना है, यह लिंक एक अच्छा स्पष्टीकरण देता है: http://gcc.gnu.org/onlinedocs/gcc/Name-lookup.html –

0

मैं इसे ऑपरेटरों को पूरी तरह से कॉल करने के लिए उपयोग करूंगा (नीचे वापसी और पैरामीटर प्रकार कोड बनाने के लिए सिर्फ डमी हैं)।

struct F { 
    void operator[](int); 
    void operator()(); 

    void f() { 
    (*this)[n]; 
    (*this)(); 
    } 

    void g() { 
    operator[](n); 
    operator()(); 
    } 
}; 

मुझे *this वाक्यविन्यास अधिक पसंद है। इसमें थोड़ा अलग अर्थपूर्ण है, जिसमें *this का उपयोग सदस्य के समान नाम के साथ गैर-सदस्य ऑपरेटर फ़ंक्शंस को छिपाएगा।

+0

आपका क्या मतलब है "' * यह सदस्य के समान नाम के साथ गैर-सदस्य ऑपरेटर फ़ंक्शंस को छिपाएगा "? क्या आप एक उदाहरण प्रदान कर सकते हैं? – rlbond

+0

उदाहरण: 'संरचना ए {शून्य ऑपरेटर *(); शून्य एफ(); }; शून्य ऑपरेटर * (ए, ए); शून्य ए :: एफ() {ए ए; ऑपरेटर * (ए, ए); } '<- यह बीमार है, क्योंकि सदस्य ऑपरेटर * वैश्विक ऑपरेटर को छुपाता है *। लेकिन अगर आप 'ए * ए' (अभिव्यक्ति वाक्यविन्यास) लिखते हैं, तो यह ठीक काम करेगा, क्योंकि लुकअप सदस्यों और गैर-सदस्यों के लिए अलग होगा। –

+0

(मानक 13.3.1.2/10 को एक बेहतर उदाहरण दिखाता है)। –

0

बहुत अच्छे उत्तर हैं, लेकिन उनमें से कोई भी इस बात का जिक्र नहीं करता है कि> स्रोत कोड में इसे पढ़ने में आसान बनाता है, खासकर जब आप कुछ लंबे फ़ंक्शन का कोड पढ़ रहे हैं, लेकिन यहां तक ​​कि एक छोटा फ़ंक्शन भी, एक कोड की कल्पना करें :

bool Class::Foo() 
{ 
    return SomeValue; 
} 

इस कोड को देखने से, आप स्पष्ट रूप से नहीं जानते कि कुछवैल्यू क्या है।यह भी कुछ #define, या स्थिर चर हो सकता है, लेकिन अगर आप

bool Class::Foo() 
{ 
    return this->SomeValue; 
} 

बारे में आप स्पष्ट रूप से जानते हैं कि SomeValue एक ही कक्षा के एक गैर स्थिर सदस्य चर रहा है।

तो यह आपको यह सुनिश्चित करने में मदद नहीं करता है कि आपके कार्यों या चर का नाम किसी अन्य नाम से संघर्ष नहीं करेगा, लेकिन यह दूसरों के लिए स्रोत कोड को पढ़ने और समझने में आसान बनाता है, एक स्वयं दस्तावेज़ लिखना स्रोत कोड कभी-कभी बहुत महत्वपूर्ण भी होता है।

2

एक और मामला, सी ++ 11 के बाद दृश्यों पर पहुंचा है, जहां this पर कब्जा कर लिया गया है।

आप की तरह कुछ हो सकता है:

class Example 
{ 
    int x; 
public: 
    std::function<void()> getIncrementor() 
    { 
    return [this]() -> void 
    { 
     ++(this->x); 
    } 
    } 
}; 

यद्यपि आपका लैम्ब्डा एक वर्ग के भीतर उत्पन्न होता है, यह केवल उन्हें कब्जा कर स्थानीय चर के लिए उपयोग होगा या this पर कब्जा (अपने संकलक सी ++ 14 करता है तो) । दूसरे मामले में, लैम्ब्डा के शरीर के अंदर, बस x नहीं है, लेकिन केवल this->x है।

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