117

this->memberクラスのメソッドを明示的に記述する必要があるのはいつですか?

4

12 に答える 12

134

通常、そうする必要はありません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->、コンパイラは の処理方法を認識しませiAiが実際に のメンバーであることを示す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
    }

};
于 2009-06-14T18:12:35.210 に答える
34

メソッド内で既存のメンバーと同じ名前のローカル変数を宣言する場合、ローカル変数の代わりに this->var を使用してクラス メンバーにアクセスする必要があります。

#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

于 2009-06-14T18:10:39.270 に答える
22

thisポインターを明示的に使用する必要がある理由はいくつかあります。

  • オブジェクトへの参照を何らかの関数に渡したい場合。
  • メンバーオブジェクトと同名のローカル宣言オブジェクトがある場合。
  • 依存する基本クラスのメンバーにアクセスしようとしている場合。
  • コード内のメンバー アクセスを視覚的に明確にするために表記法を好む人もいます。
于 2009-06-14T18:18:30.607 に答える
7

私は通常、これが特に好きではありませんが、他の人がこれを使用しているのを見たことがあります->単にインテリセンスから助けを得るためです!

于 2009-06-14T23:29:25.603 に答える
7

this using を使用しなければならないケースはほとんどありませんが、ポインタを使用しthisて問題を解決する方法がある場合もあります。

1)利用可能な代替手段: @ASk で示されているように、ローカル変数とクラス メンバーの間のあいまいさを解決します。

2)代替手段なし:thisメンバー関数からポインタまたは参照を返すため。operator+これは、operator-operator=、 などをオーバーロードするときに頻繁に実行されます (実行する必要があります) 。

class Foo
{
  Foo& operator=(const Foo& rhs)
  {
    return * this;
  }
};

これを行うと、1 行のコードでオブジェクトに対して複数の操作を実行する「メソッド チェーン」と呼ばれるイディオムが可能になります。そのような:

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ローカルのために使用しています。

于 2009-06-15T04:32:40.470 に答える
6
  1. メンバー変数がローカル変数によって隠される場所
  2. インスタンスメソッド/変数を呼び出していることを明示的に明確にしたい場合


一部のコーディング標準では、アプローチ (2) を使用すると、コードが読みやすくなると主張されています。

例:
MyClass に「count」というメンバー変数があるとします。

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

   .....
   count++;
   this->count = count;
}
于 2009-06-14T18:13:15.097 に答える
5

もう 1 つのケースは、オペレーターを呼び出す場合です。たとえば、代わりに

bool Type::operator!=(const Type& rhs)
{
    return !operator==(rhs);
}

あなたが言うことができます

bool Type::operator!=(const Type& rhs)
{
    return !(*this == rhs);
}

どちらが読みやすいかもしれません。もう 1 つの例は、コピー アンド スワップです。

Type& Type::operator=(const Type& rhs)
{
    Type temp(rhs);
    temp.swap(*this);
}

なぜ書かれていないのかわかりませんがswap(temp)、これはよくあることのようです。

于 2009-06-14T18:24:41.030 に答える
4

this-> を使用する必要があるのは、2 つの潜在的な名前空間に同じ名前のシンボルがある場合のみです。たとえば、次のとおりです。

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->」を明示的に使用する必要があります。

于 2009-06-14T18:11:53.043 に答える
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)();
    }
}

this->member だけでなく、これの他の使用法を示すのに役立つことを願っています。

于 2009-06-14T18:22:11.130 に答える
3

thisパラメータ/ローカル変数とメンバー変数の間のあいまいさを解消するために使用する必要があります。

class Foo
{
protected:
  int myX;

public:
  Foo(int myX)
  {
    this->myX = myX; 
  }
};
于 2009-06-14T18:11:28.830 に答える
3

ポインターの主な (または唯一の) 目的はthis、メンバー関数を呼び出すために使用されるオブジェクトを指すことです。

この目的に基づいて、thisポインターを使用するだけで問題を解決できる場合があります。

たとえば、引数が同じクラスオブジェクトであるメンバー関数で呼び出し元のオブジェクトを返す必要があります。

class human {

... 

human & human::compare(human & h){
    if (condition)
        return h;       // argument object
    else 
        return *this;   // invoking object
    }
};
于 2015-09-02T15:09:27.120 に答える
2

私は、Effective C++ の本で、"this" ポインターを明示的に使用する別の興味深い事例を見つけました。

たとえば、次のような const 関数があるとします。

  unsigned String::length() const

呼び出しごとに文字列の長さを計算したくないため、次のような方法でキャッシュする必要があります

  unsigned String::length() const
  {
    if(!lengthInitialized)
    {
      length = strlen(data);
      lengthInitialized = 1;
    }
  }

しかし、これはコンパイルされません - const 関数でオブジェクトを変更しています。

これを解決するには、これを非 const の this にキャストする必要あります

  String* const nonConstThis = (String* const) this;

次に、上記でできるようになります

  nonConstThis->lengthInitialized = 1;
于 2009-06-14T18:27:33.707 に答える