मुझे this->member
कक्षा की एक विधि में स्पष्ट रूप से कब लिखना चाहिए ?
research.att.com/~bs/
है अब है stroustrup.com
। नया लिंक: stroustrup.com/bs_faq2.html#this
मुझे this->member
कक्षा की एक विधि में स्पष्ट रूप से कब लिखना चाहिए ?
research.att.com/~bs/
है अब है stroustrup.com
। नया लिंक: stroustrup.com/bs_faq2.html#this
जवाबों:
आमतौर पर, आपके पास नहीं है, this->
निहित है।
कभी-कभी, एक नाम अस्पष्टता है, जहां इसका उपयोग कक्षा के सदस्यों और स्थानीय चर को खंडित करने के लिए किया जा सकता है। हालांकि, यहां एक बिल्कुल अलग मामला है जहां this->
स्पष्ट रूप से आवश्यक है।
निम्नलिखित कोड पर विचार करें:
template<class T>
struct A {
int i;
};
template<class T>
struct B : A<T> {
int foo() {
return this->i;
}
};
int main() {
B<int> b;
b.foo();
}
यदि आप छोड़ देते हैं this->
, तो संकलक को पता नहीं है कि कैसे इलाज करना है i
, क्योंकि यह सभी तात्कालिकता में मौजूद हो सकता है या नहीं A
। यह बताने के लिए कि i
वास्तव में किसी सदस्य के A<T>
लिए T
, this->
उपसर्ग की आवश्यकता है।
नोट: यह अभी भी this->
उपसर्ग का उपयोग करके छोड़ना संभव है :
template<class T>
struct B : A<T> {
using A<T>::i; // explicitly refer to a variable in the base class
int foo() {
return i; // i is now known to exist
}
};
i
अस्तित्व में नहीं हो सकता है A
। क्या मुझे एक उदाहरण मिल सकता है?
template<> struct A<float> { float x; };
यदि आप किसी मौजूदा सदस्य के समान नाम के साथ स्थानीय चर घोषित करते हैं, तो आपको स्थानीय चर के बजाय कक्षा सदस्य तक पहुंचने के लिए इस-> संस्करण का उपयोग करना होगा।
#include <iostream>
using namespace std;
class A
{
public:
int a;
void f() {
a = 4;
int a = 5;
cout << a << endl;
cout << this->a << endl;
}
};
int main()
{
A a;
a.f();
}
प्रिंट:
५
४
ऐसे कई कारण हैं जिनकी वजह से आपको this
सूचक को स्पष्ट रूप से उपयोग करने की आवश्यकता हो सकती है ।
हालाँकि मैं आमतौर पर इसे पसंद नहीं करता, लेकिन मैंने देखा है कि अन्य लोग इसका उपयोग करते हैं-> बस अंतर्मुखता से सहायता पाने के लिए!
कुछ कोडिंग मानक दृष्टिकोण (2) का उपयोग करते हैं क्योंकि वे दावा करते हैं कि यह कोड को पढ़ना आसान बनाता है।
उदाहरण:
मान लें कि MyClass में 'काउंट' नामक एक सदस्य चर है
void MyClass::DoSomeStuff(void)
{
int count = 0;
.....
count++;
this->count = count;
}
एक अन्य मामला है जब ऑपरेटरों को आमंत्रित करना। के बजाय
bool Type::operator!=(const Type& rhs)
{
return !operator==(rhs);
}
तुम कह सकते हो
bool Type::operator!=(const Type& rhs)
{
return !(*this == rhs);
}
जो अधिक पठनीय हो सकता है। एक और उदाहरण है कॉपी-एंड-स्वैप:
Type& Type::operator=(const Type& rhs)
{
Type temp(rhs);
temp.swap(*this);
}
मुझे नहीं पता कि यह क्यों नहीं लिखा गया है swap(temp)
लेकिन यह आम बात है।
const
सदस्यीय फ़ंक्शन को अस्थायी ( Type(rhs).swap(*this);
कानूनी और सही है) पर कॉल कर सकते हैं, लेकिन एक अस्थायी गैर-कॉन्स्टेंस रेफ़रेंस पैरामीटर (कंपाइलर रिजेक्ट के swap(Type(rhs));
साथ-साथ this->swap(Type(rhs));
) पर बाँध नहीं सकता है
ऐसे कुछ मामले हैं जहां उपयोग this
करना आवश्यक है, और कुछ अन्य हैं जहां this
पॉइंटर का उपयोग करना एक समस्या को हल करने का एक तरीका है।
1) उपलब्ध विकल्प : स्थानीय चर और वर्ग के सदस्यों के बीच अस्पष्टता को हल करने के लिए, जैसा कि @ASk द्वारा सचित्र है ।
2) कोई वैकल्पिक नहीं:this
एक सदस्य फ़ंक्शन से एक सूचक या संदर्भ वापस करने के लिए । यह अक्सर किया जाता है (और किया जाना चाहिए) जब अधिक भार operator+
, operator-
, operator=
, आदि:
class Foo
{
Foo& operator=(const Foo& rhs)
{
return * this;
}
};
ऐसा करना एक मुहावरे को " विधि जंजीर " के रूप में जाना जाता है , जहाँ आप किसी ऑब्जेक्ट पर कोड की एक पंक्ति में कई कार्य करते हैं। जैसे कि:
Student st;
st.SetAge (21).SetGender (male).SetClass ("C++ 101");
कुछ लोग इस सहमति को मानते हैं, अन्य इसे घृणा मानते हैं। मुझे बाद वाले समूह में गिनें।
3) कोई वैकल्पिक नहीं: निर्भर प्रकारों में नामों को हल करने के लिए। यह इस उदाहरण में टेम्प्लेट का उपयोग करते समय आता है:
#include <iostream>
template <typename Val>
class ValHolder
{
private:
Val mVal;
public:
ValHolder (const Val& val)
:
mVal (val)
{
}
Val& GetVal() { return mVal; }
};
template <typename Val>
class ValProcessor
:
public ValHolder <Val>
{
public:
ValProcessor (const Val& val)
:
ValHolder <Val> (val)
{
}
Val ComputeValue()
{
// int ret = 2 * GetVal(); // ERROR: No member 'GetVal'
int ret = 4 * this->GetVal(); // OK -- this tells compiler to examine dependant type (ValHolder)
return ret;
}
};
int main()
{
ValProcessor <int> proc (42);
const int val = proc.ComputeValue();
std::cout << val << "\n";
}
4) विकल्प उपलब्ध: कोडिंग शैली के एक भाग के रूप में, दस्तावेज़ों के लिए जो चर चर सदस्य हैं जो स्थानीय चर के विपरीत हैं। मैं एक अलग नामकरण योजना पसंद करता हूं, जहां सदस्य varibales स्थानीय लोगों के समान नाम कभी नहीं रख सकते। वर्तमान में मैं mName
सदस्यों के लिए और name
स्थानीय लोगों के लिए उपयोग कर रहा हूं ।
आपको केवल इसका उपयोग करना होगा-> यदि आपके पास दो संभावित नामस्थानों में समान नाम वाला प्रतीक है। उदाहरण के लिए:
class A {
public:
void setMyVar(int);
void doStuff();
private:
int myVar;
}
void A::setMyVar(int myVar)
{
this->myVar = myVar; // <- Interesting point in the code
}
void A::doStuff()
{
int myVar = ::calculateSomething();
this->myVar = myVar; // <- Interesting point in the code
}
कोड में दिलचस्प बिंदुओं पर, myVar का संदर्भ स्थानीय (पैरामीटर या चर) myVar को संदर्भित करेगा। वर्ग के सदस्य तक पहुँचने के लिए जिसे myVar भी कहा जाता है, आपको "यह->" का स्पष्ट रूप से उपयोग करने की आवश्यकता है।
this->
बचने के लिए उस तुच्छ का एक उपयोग है (बस स्थानीय चर को एक अलग नाम दें)। के सभी वास्तव में दिलचस्प उपयोग this
भी इस जवाब से उल्लेख नहीं किया गया है।
इसके लिए अन्य उपयोग (जैसा कि मैंने सोचा था कि जब मैं सारांश पढ़ता हूं और आधा प्रश्न ...।), अन्य उत्तरों में असहमति (बुरा) नामकरण को अस्वीकार कर देता है, यदि आप वर्तमान वस्तु को डालना चाहते हैं, तो इसे एक फ़ंक्शन ऑब्जेक्ट में बांधें या इसका उपयोग पॉइंटर-टू-मेंबर के साथ करें।
void Foo::bar() {
misc_nonconst_stuff();
const Foo* const_this = this;
const_this->bar(); // calls const version
dynamic_cast<Bar*>(this)->bar(); // calls specific virtual function in case of multi-inheritance
}
void Foo::bar() const {}
void Foo::baz() {
for_each(m_stuff.begin(), m_stuff.end(), bind(&Foo:framboozle, this, _1));
for_each(m_stuff.begin(), m_stuff.end(), [this](StuffUnit& s) { framboozle(s); });
}
void Foo::framboozle(StuffUnit& su) {}
std::vector<StuffUnit> m_stuff;
void Foo::boz() {
bez(&Foo::bar);
bez(&Foo::baz);
}
void Foo::bez(void (Foo::*func_ptr)()) {
for (int i=0; i<3; ++i) {
(this->*func_ptr)();
}
}
आशा है कि यह इसके अलावा अन्य उपयोगों को दिखाने में मदद करता है-> सदस्य।
आपको this
एक पैरामीटर / स्थानीय चर और सदस्य चर के बीच खंडन करने के लिए उपयोग करने की आवश्यकता है ।
class Foo
{
protected:
int myX;
public:
Foo(int myX)
{
this->myX = myX;
}
};
this
सूचक का मुख्य (या मैं कह सकता हूं, एकमात्र) उद्देश्य यह है कि यह सदस्य फ़ंक्शन को लागू करने के लिए उपयोग की जाने वाली वस्तु को इंगित करता है।
इस उद्देश्य के आधार पर, हमारे पास कुछ मामले हो सकते हैं जो केवल this
सूचक का उपयोग करके समस्या को हल कर सकते हैं।
उदाहरण के लिए, हमें किसी सदस्य फ़ंक्शन में इनवॉइसिंग ऑब्जेक्ट को तर्क के साथ वापस करना होगा एक ही वर्ग ऑब्जेक्ट है:
class human {
...
human & human::compare(human & h){
if (condition)
return h; // argument object
else
return *this; // invoking object
}
};
मुझे प्रभावी C ++ पुस्तक में "यह" सूचक के स्पष्ट उपयोग का एक और दिलचस्प मामला मिला।
उदाहरण के लिए, मान लें कि आपके पास एक कास्ट फ़ंक्शन है जैसे
unsigned String::length() const
आप प्रत्येक कॉल के लिए स्ट्रिंग की लंबाई की गणना नहीं करना चाहते हैं, इसलिए आप इसे कुछ ऐसा करने के लिए कैश करना चाहते हैं
unsigned String::length() const
{
if(!lengthInitialized)
{
length = strlen(data);
lengthInitialized = 1;
}
}
लेकिन यह संकलित नहीं करेगा - आप ऑब्जेक्ट को एक कास्ट फ़ंक्शन में बदल रहे हैं।
चाल हल करने के लिए इस कास्टिंग की आवश्यकता है इस -स्थिरांक गैर एक करने के लिए इस :
String* const nonConstThis = (String* const) this;
फिर, आप ऊपर कर सकेंगे
nonConstThis->lengthInitialized = 1;
length
उत्परिवर्तित कर सकते हैं , या इसे एक नेस्टेड संरचना में भी रख सकते हैं। कब्ज को दूर करना लगभग एक अच्छा विचार नहीं है।
const
सदस्य कार्यों से बदला जाना है, तो यह होना चाहिए mutable
। अन्यथा आप जीवन को एक अन्य रखवाले के लिए और अधिक जटिल बना रहे हैं।