3

メソッドのクラスの一部であるメンバーデータ/関数にアクセスする適切な方法は何ですか?3つの手段があるようです:

class test{
    private:
        int variable;
    public:
        void setVariable(int value) {
            variable = value;        // method 1, using the variable name directly
            this->variable = value;  // method 2, via pointer dereference of 'this'
            test::variable = value;  // method 3, via scope operator
        }
};

私が知る限り、それらはすべて機能しているようです。それらは同等ですか?スタイル/一貫性のほかに、一方を他方の上に使用する理由はありますか?

4

8 に答える 8

3

一般的には問題ではないので、より単純なオプションmember = value;が推奨されます。場合によっては、ローカル変数にあいまいさがあり、this->プレフィックスで修飾することができますが、より良いアプローチは、あいまいさを完全に回避することです。

ただし、それが問題となるいくつかのコーナーケースがあります。仮想関数を処理する場合、修飾名(type::member)を使用すると、ランタイムディスパッチが無効になり、レベルの最終的なオーバーライドtypeが呼び出されるようになります。

struct base {
   virtual int f() { return 1; }
};
struct derived : base {
   virtual int f() { return 2; }
   void g() {
      std::cout << f() << "\n";
      std::cout << derived::f() << "\n";
   }
};
struct mostderived : derived {
   virtual int f() { return 3; }
};
int main() {
   mostderived d;
   d.g();            // 3 2
}

テンプレートクラスと継承を処理する場合、ルックアップは2つのフェーズで実行されます。最初のフェーズでは、依存しない名前を解決する必要があります。非修飾名は非依存名であるため、場合によっては、またはのいずれthis->type::で修飾する必要があり、上記の区別が引き続き適用されます。追加の資格は、名前を依存させるのに役立ちます:

template <typename T>
struct derived : T {
   void g() {
      // std::cout << f() << "\n";    // Error, cannot resolve f() [*]
      this->f();                      // Ok, pick final overrider at runtime 
      derived::f();                   // Ok, pick overrider here: base::f()
   }
};
struct base {
   virtual int f() { return 1; }
};
struct mostderived : derived<base> {
   virtual int f() { return 3; }
};
int main() {
   mostderived d;
   d.g();                             // 3, 1
}
于 2012-11-07T19:15:19.247 に答える
3

あなたが言及するように、スタイルと一貫性に加えて、曖昧さを解消するために特定の構文を使用しなければならない場合があります。

「メソッド2」は、ローカル変数とクラスメンバーの間の曖昧さを解消するために使用できます。

「メソッド3」を使用すると、クラス階層のさまざまな場所にある同じ名前のフィールド間で曖昧さを解消できます。

于 2012-11-07T18:43:36.837 に答える
1
  • 方法1:これは一般的な方法です。
  • 方法2:これはそれを行うための最良かつ最も一貫した方法です。何が起こっているのかを読んで理解することが非常に明確になります。
  • 方法3:実際のコードで行われるのを見たことがありません。

補足としてメソッド1を使用するときに、関数パラメーターおよびメンバー変数と名前の競合がある場合、関数パラメーターがメンバー変数に対して使用されます。

私たちが持っている場合:

void setVariable(int variable) {
    variable = variable;        // method 1, this does not change the member variable.
    this->variable = variable;  // method 2, via pointer dereference of 'this'
    test::variable = variable;  // method 3, via scope operator
}
于 2012-11-07T18:43:30.127 に答える
1

オブジェクト内のコードの場合、通常は違いがないため、通常はそれを使用variable = value;して実行するのが最もクリーンです。

テンプレートでは、変数名を単独で使用するだけであいまいになり、this->variableそのあいまいさを取り除くことができる場合がありますが、これは非常にまれであるため、一度は役立つ可能性があるという理由だけで、定期的に使用することは絶対にありませthis->everything。しばらくして。

于 2012-11-07T18:45:06.517 に答える
0

これは、クラスのオーバーロードされた演算子での比較によく使用されるポインターです。その用途の1つは、関数で渡されるパラメーターがオブジェクト自体と同じである場合です。次に例を示します。

class CDummy {
  public:
    int isitme (CDummy& param);
};

int CDummy::isitme (CDummy& param)
{
  if (&param == this) return true;
  else return false;
} 

これは、オブジェクト自体へのポインタを返すためにも使用されます

ClassEx ClassEx::Func(//params)
{
    //code
    return *this;
}

通常の比較に関しては、使用するのがより効率的であるvalue代わりに、値をチェックしない限りthis->value、の使用はあいまいです。this->

于 2012-11-07T18:44:03.273 に答える
0

パフォーマンスに違いはありません。これ::は、フィールドの同じ名前のローカル変数や、派生クラスのフィールドの同じ名前のフィールドを宣言する基本クラスがある場合など、あいまいさを回避するために使用されます。の型はオブジェクトへのポインタ->であるため、がサポートされています。コンパイラはを受け入れる必要があります。これは、あいまいさを回避したり、コードをより明確にするためにも使用できます。thisthis->something

于 2012-11-07T18:46:55.147 に答える
0

そして、上記の答えに追加するために:いくつかのコードスタイルは、またはのような固定プレフィックスを使用してメンバー変数を識別するのが好き_ですm。「方法2」を使用することは、コードでこの明確さを達成するためのもう1つの(そして非常に優れた方法です)。

優先this->valueするvalueことも、std::cin代わりにcinを使用することに少し似ていusing namespace stdます。

于 2012-11-07T19:45:49.003 に答える
-1

方法1を使用する

variable = value;

新しいキーボードを頻繁に購入する手間が省けます。

(私はコーヒーを飲み続けるのをやめるべきだと言っていました!)

于 2012-11-07T18:42:50.707 に答える