আমি কখন এই "পয়েন্টার" এর সুস্পষ্ট ব্যবহার করব?


101

আমি কখন this->memberক্লাসের পদ্ধতিতে স্পষ্টভাবে লিখব ?


17
আমি নিশ্চিত এটি একটি ডুপ, তবে এটি অবশ্যই অদম্য। প্রথমবারের মতো নয়, আমি ইচ্ছা করি এই পয়েন্টারটিকে স্ব বলা হত!

5
শুধু তা-ই নয়, আমার ইচ্ছা এটি একটি রেফারেন্স হয়।
rlbond

4
একই। : | এখানে কেন, উপায়: গবেষণা.
att.com/~bs/bs_faq2.html# তম

11
এই পদ্ধতিটি স্পষ্টতই কাজ করে না যদি ব্যক্তি উত্তরটি না জানে।
ASk

4
@ জোহানএইচ .: এইচএম, দেখতে research.att.com/~bs/এখন দেখা যাচ্ছে stroustrup.com। নতুন লিঙ্ক: stroustrup.com/bs_faq2.html# তম
GManNGG

উত্তর:


121

সাধারণত, আপনার প্রয়োজন হয় না, 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
    }

};

8
ঘোষণা ব্যবহারের দুর্দান্ত ব্যবহার :)
ফয়সাল ভালি

4
এটি একটি বিশেষভাবে বাজে মামলা। আমাকে এর আগেও কামড়েছে।
জেসন বেকার

5
এটি একটি নির্বোধ প্রশ্ন হতে পারে তবে আমি বুঝতে পারি না কেন iএটি বিদ্যমান নেই A। আমি একটি উদাহরণ পেতে পারি?
ক্যাম জ্যাকসন

4
@ ক্যামজ্যাকসন আমি ভিজ্যুয়াল স্টুডিওতে কোডটি চেষ্টা করেছি। "এই->" এর অস্তিত্ব আছে কি নেই ফলাফলগুলি একই রকম। কোন ধারণা?
পেং ঝাং

8
@ ক্যামজ্যাকসন: যে কোনও ক্লাস টাইপ করতে পারে:template<> struct A<float> { float x; };
ম্যাক

31

যদি আপনি কোনও বিদ্যমান সদস্য হিসাবে একই নামে একটি পদ্ধতিতে স্থানীয় ভেরিয়েবল ঘোষণা করেন, স্থানীয় ভেরিয়েবলের পরিবর্তে শ্রেণি সদস্যকে অ্যাক্সেস করতে আপনাকে এই-> ভার ব্যবহার করতে হবে।

#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


4
আমি আরও ভালভাবে কৌট ব্যবহার করতে চাই << এ :: এ << এন্ডেল; পরিবর্তে. এই ক্ষেত্রে `` এটি "গুরুত্বহীন
সিদ্ধন্ত 3s

4
আমি বরং "এম_এ" বা "এ_" এর মতো সম্মেলনের সাথে নামের সংঘাত এড়াতে চাই।
টম

19

বিভিন্ন কারণে আপনার thisস্পষ্টতই পয়েন্টার ব্যবহারের প্রয়োজন হতে পারে ।

  • যখন আপনি কিছু ফাংশনে আপনার অবজেক্টের একটি রেফারেন্স দিতে চান।
  • যখন সদস্য অবজেক্টের মতো একই নামে একটি স্থানীয়ভাবে ঘোষিত অবজেক্ট থাকে।
  • আপনি যখন নির্ভর বেস ক্লাসের সদস্যদের অ্যাক্সেস করার চেষ্টা করছেন ।
  • কিছু লোক তাদের কোডটিতে দৃষ্টিভঙ্গি সদস্য অ্যাক্সেসকে স্বরলিপিটি পছন্দ করেন।

7

যদিও আমি সাধারণত এটি পছন্দ করি না, তবুও আমি অন্যদের এটি-> সহজেই ইন্টেলিজেন্সের সাহায্য নিতে ব্যবহার করতে দেখেছি!


6
  1. যেখানে একটি সদস্য ভেরিয়েবল স্থানীয় ভেরিয়েবল দ্বারা আড়াল করা হবে
  2. আপনি যদি কেবল এটি স্পষ্ট করে বলতে চান যে আপনি একটি উদাহরণ পদ্ধতি / ভেরিয়েবল কল করছেন


কিছু কোডিং স্ট্যান্ডার্ড পদ্ধতির (2) ব্যবহার করে কারণ তারা দাবি করে যে কোডটি পড়া সহজ করে তোলে।

উদাহরণ:
ধরে নিন মাইক্লাসের একটি সদস্য ভেরিয়েবল আছে যার নাম 'কাউন্ট'

void MyClass::DoSomeStuff(void)
{
   int count = 0;

   .....
   count++;
   this->count = count;
}

6

কয়েকটি ক্ষেত্রেই ব্যবহার করা 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স্থানীয়দের জন্য ব্যবহার করছি ।


5

অপারেটরদেরকে আহ্বান করার সময় অন্য একটি ঘটনা। যেমন পরিবর্তে

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));)
বেন ভয়েগট

4

আপনার কেবলমাত্র এটি ব্যবহার করতে হবে - যদি আপনার দুটি সম্ভাব্য নেমস্পেসে একই নামের একটি প্রতীক থাকে। উদাহরণস্বরূপ নিন:

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এমনকি এই উত্তর দ্বারা উল্লেখ করা হয় না।
মাস্টার -

4

এর জন্য অন্যান্য ব্যবহারগুলি (যেমন আমি ভেবেছিলাম যখন আমি সংক্ষিপ্তসারটি পড়ি এবং অর্ধেক প্রশ্নটি ...।), অন্য উত্তরে নাম বদলে দেওয়া (খারাপ) উপেক্ষা করা যদি আপনি বর্তমান বস্তুটি কাস্ট করতে চান তবে এটি একটি ফাংশন অবজেক্টে আবদ্ধ করুন অথবা এটি পয়েন্টার-টু-সদস্য সহ ব্যবহার করুন।

কাস্ট

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)();
    }
}

আশা করি এটি কেবল এই-> সদস্যের চেয়ে অন্যান্য ব্যবহারগুলি প্রদর্শন করতে সহায়তা করে।


3

thisএকটি পরামিতি / স্থানীয় ভেরিয়েবল এবং সদস্য ভেরিয়েবলের মধ্যে বিচ্ছিন্ন করতে আপনাকে ব্যবহার করতে হবে।

class Foo
{
protected:
  int myX;

public:
  Foo(int myX)
  {
    this->myX = myX; 
  }
};

4
না, আপনি না প্রয়োজন এটা, আপনি পারেন ব্যবহার করুন। আপনি ফাংশন আর্গুমেন্টের জন্য পৃথক নামও ব্যবহার করতে পারেন, এতে একই নামের সাথে দুটি সত্তা না থাকার সুবিধা রয়েছে।
মাস্টার -

3

thisপয়েন্টারের মূল (বা আমি বলতে পারি) একমাত্র উদ্দেশ্য হ'ল এটি সদস্য ফাংশনটি আহ্বান করতে ব্যবহৃত বস্তুর দিকে নির্দেশ করে points

এই উদ্দেশ্যে ভিত্তিতে, আমাদের কিছু ক্ষেত্রে থাকতে পারে যা কেবলমাত্র thisপয়েন্টার ব্যবহার করে সমস্যার সমাধান করতে পারে।

উদাহরণস্বরূপ, আর্গুমেন্ট সহ একটি সদস্য ফাংশনে আমন্ত্রণকারী বস্তুটি আমাদের একই শ্রেণীর অবজেক্টটি ফিরিয়ে দিতে হবে:

class human {

... 

human & human::compare(human & h){
    if (condition)
        return h;       // argument object
    else 
        return *this;   // invoking object
    }
};

2

কার্যকর সি ++ বইয়ের "এই" পয়েন্টারটির স্পষ্ট ব্যবহারের আর একটি আকর্ষণীয় ঘটনা আমি পেয়েছি।

উদাহরণস্বরূপ, বলুন আপনার মত একটি কনস্টেন্ট ফাংশন রয়েছে

  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;

4
অথবা আপনি lengthপরিবর্তন করতে পারবেন , বা এমনকি নেস্টেড স্ট্রাক্টে এটি রাখতে পারেন। দৃness়তা দূরে ফেলে দেওয়া প্রায় কখনওই ভাল ধারণা নয়।
রিচার্ড জে রস তৃতীয়

4
দয়া করে না। সদস্যের constসদস্য কার্য থেকে যদি সদস্যকে পরিবর্তন করতে হয় তবে তা হওয়া উচিত mutable। অন্যথায় আপনি অন্য রক্ষণাবেক্ষণকারীদের জন্য জীবনকে আরও জটিল করে তুলছেন।
ডেভিড রদ্রিগেজ - ফ্রি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.