আমি কখন this->member
ক্লাসের পদ্ধতিতে স্পষ্টভাবে লিখব ?
research.att.com/~bs/
এখন দেখা যাচ্ছে stroustrup.com
। নতুন লিঙ্ক: stroustrup.com/bs_faq2.html# তম
আমি কখন this->member
ক্লাসের পদ্ধতিতে স্পষ্টভাবে লিখব ?
research.att.com/~bs/
এখন দেখা যাচ্ছে stroustrup.com
। নতুন লিঙ্ক: stroustrup.com/bs_faq2.html# তম
উত্তর:
সাধারণত, আপনার প্রয়োজন হয় না, this->
নিহিত থাকে।
কখনও কখনও, একটি নামের অস্পষ্টতা রয়েছে, যেখানে এটি শ্রেণিবদ্ধ সদস্য এবং স্থানীয় ভেরিয়েবলকে অপ্রস্তুত করতে ব্যবহার করা যেতে পারে। তবে, এখানে একটি সম্পূর্ণ আলাদা কেস যেখানে this->
স্পষ্টভাবে প্রয়োজন হয় required
নিম্নলিখিত কোড বিবেচনা করুন:
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();
}
মুদ্রণ:
5
4
বিভিন্ন কারণে আপনার this
স্পষ্টতই পয়েন্টার ব্যবহারের প্রয়োজন হতে পারে ।
যদিও আমি সাধারণত এটি পছন্দ করি না, তবুও আমি অন্যদের এটি-> সহজেই ইন্টেলিজেন্সের সাহায্য নিতে ব্যবহার করতে দেখেছি!
কিছু কোডিং স্ট্যান্ডার্ড পদ্ধতির (2) ব্যবহার করে কারণ তারা দাবি করে যে কোডটি পড়া সহজ করে তোলে।
উদাহরণ:
ধরে নিন মাইক্লাসের একটি সদস্য ভেরিয়েবল আছে যার নাম 'কাউন্ট'
void MyClass::DoSomeStuff(void)
{
int count = 0;
.....
count++;
this->count = count;
}
কয়েকটি ক্ষেত্রেই ব্যবহার করা this
আবশ্যক যেখানে ব্যবহার করা আবশ্যক এবং অন্য কিছু রয়েছে যেখানে this
পয়েন্টার ব্যবহার করা সমস্যা সমাধানের এক উপায়।
1) বিকল্প উপলব্ধ : স্থানীয় ভেরিয়েবল এবং শ্রেণীর সদস্যদের মধ্যে অস্পষ্টতা সমাধানের জন্য @ এএসকে দ্বারা চিত্রিত ।
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) বিকল্প উপলব্ধ: কোডিং শৈলীর অংশ হিসাবে, স্থানীয় ভেরিয়েবলের বিপরীতে কোন ভেরিয়েবল সদস্য ভেরিয়েবল হয় তা নথিভুক্ত করতে। আমি আলাদা নামকরণের স্কিমটি পছন্দ করি যেখানে সদস্যের বর্ণগুলি স্থানীয় লোকের মতো একই নাম থাকতে পারে না। বর্তমানে আমি mName
সদস্যদের এবং name
স্থানীয়দের জন্য ব্যবহার করছি ।
অপারেটরদেরকে আহ্বান করার সময় অন্য একটি ঘটনা। যেমন পরিবর্তে
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));
)
আপনার কেবলমাত্র এটি ব্যবহার করতে হবে - যদি আপনার দুটি সম্ভাব্য নেমস্পেসে একই নামের একটি প্রতীক থাকে। উদাহরণস্বরূপ নিন:
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
}
কোডের আকর্ষণীয় পয়েন্টগুলিতে, মাইভারকে উল্লেখ করে স্থানীয় (প্যারামিটার বা ভেরিয়েবল) মাইভারটি উল্লেখ করা হবে। ক্লাস মেম্বারটিকে মাইভার নামেও অ্যাক্সেস করতে আপনার স্পষ্টভাবে "এটি->" ব্যবহার করতে হবে।
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
পয়েন্টারের মূল (বা আমি বলতে পারি) একমাত্র উদ্দেশ্য হ'ল এটি সদস্য ফাংশনটি আহ্বান করতে ব্যবহৃত বস্তুর দিকে নির্দেশ করে points
এই উদ্দেশ্যে ভিত্তিতে, আমাদের কিছু ক্ষেত্রে থাকতে পারে যা কেবলমাত্র this
পয়েন্টার ব্যবহার করে সমস্যার সমাধান করতে পারে।
উদাহরণস্বরূপ, আর্গুমেন্ট সহ একটি সদস্য ফাংশনে আমন্ত্রণকারী বস্তুটি আমাদের একই শ্রেণীর অবজেক্টটি ফিরিয়ে দিতে হবে:
class human {
...
human & human::compare(human & h){
if (condition)
return h; // argument object
else
return *this; // invoking object
}
};
কার্যকর সি ++ বইয়ের "এই" পয়েন্টারটির স্পষ্ট ব্যবহারের আর একটি আকর্ষণীয় ঘটনা আমি পেয়েছি।
উদাহরণস্বরূপ, বলুন আপনার মত একটি কনস্টেন্ট ফাংশন রয়েছে
unsigned String::length() const
আপনি প্রতিটি কলের জন্য স্ট্রিংয়ের দৈর্ঘ্য গণনা করতে চান না, তাই আপনি এটির মতো কিছু করে ক্যাশে করতে চান
unsigned String::length() const
{
if(!lengthInitialized)
{
length = strlen(data);
lengthInitialized = 1;
}
}
তবে এটি সংকলন করবে না - আপনি কনস্ট ফাংশনে অবজেক্টটি পরিবর্তন করছেন।
কৌতুক সমাধানের জন্য এই ভোটদান প্রয়োজন এই -const অ একটি থেকে এই :
String* const nonConstThis = (String* const) this;
তারপরে, আপনি উপরে করতে সক্ষম হবেন
nonConstThis->lengthInitialized = 1;
length
পরিবর্তন করতে পারবেন , বা এমনকি নেস্টেড স্ট্রাক্টে এটি রাখতে পারেন। দৃness়তা দূরে ফেলে দেওয়া প্রায় কখনওই ভাল ধারণা নয়।
const
সদস্য কার্য থেকে যদি সদস্যকে পরিবর্তন করতে হয় তবে তা হওয়া উচিত mutable
। অন্যথায় আপনি অন্য রক্ষণাবেক্ষণকারীদের জন্য জীবনকে আরও জটিল করে তুলছেন।