14

私は最近javascriptに多くの時間を費やし、現在C++に戻っています。メソッドからクラスメンバーにアクセスしているときは、プレフィックスを付けてフィードする傾向がありますthis->

class Foo {

  int _bar;

public:  
  /* ... */

  void setBar(int bar) {
    this->_bar = bar;
    // as opposed to
    _bar = bar;
  }
}

読んで、それがどこから来ているのかを理解しようとするとき、それは私に脳のサイクルを節約します。
これをしてはいけない理由はありますか?

4

8 に答える 8

13

クラス変数にthis->を使用することは完全に許容されます。

ただし、識別子をアンダースコアで開始したり、二重アンダースコアの識別子を含めたりしないでください__。これらの2つの経験則のいずれかに違反すると、簡単にヒットする予約済みシンボルのクラスがいくつかあります。(特に、_IdentifierStartingWithACapitalは、コンパイラーの標準によって予約されています)。

于 2012-11-13T20:08:11.953 に答える
10

原則として、経由でメンバーにアクセスするthis->ことは、物事をより明確にするのに役立つコーディングスタイルですが、それは好みの問題のようです。

_ただし、メンバーの前に(アンダースコア)を付けることも使用しているようです。それは多すぎると思います。2つのスタイルのどちらかを選択する必要があります。

于 2012-11-13T20:08:28.793 に答える
7

これをしてはいけない理由はありますか?

はい、これを行うべきではない理由があります。

でメンバー変数を参照することは、次のように名前が非表示になっている場合にのみthis->厳密に必要です。

class Foo
{
public:
    void bang(int val);
    int val;
};

void Foo::bang(int val)
{
    val = val;
}

int main()
{
    Foo foo;
    foo.val = 42;
    foo.bang(84);
    cout << foo.val;

}

このプログラムの出力は42、ではなく84bangメンバー変数が非表示になっているため、何も実行されval = valません。この場合、this->が必要です。

void Foo::bang(int val)
{
    this->val = val;
}

それ以外の場合、使用しthis->ても効果がないため、必要ありません。

それ自体は、を使用しない理由ではありませんthis->。ただし、このようなプログラムの保守は、を使用しない理由this->です。

this->次の変数がメンバー変数であることを指定するためのドキュメントの手段として使用しています。ただし、ほとんどのプログラマーにとって、それはusignthis->が実際に文書化するものではありません。this->ドキュメントの使用とは:

ここに隠されている名前があるので、私はそれを回避するために特別なテクニックを使用しています。

それはあなたが伝えたかったことではないので、あなたのドキュメントは壊れています。

名前がメンバー変数であることを文書化するために使用する代わりにthis->、メンバー変数とメソッドパラメーターが同じになることのない合理的な命名スキームを一貫して使用してください。

編集 同じアイデアの別の図を考えてみましょう。

私のコードベースで、次のことがわかったとします。

int main()
{
    int(*fn)(int) = pingpong;
    (fn)(42);
}

非常に珍しい構成ですが、熟練したC ++プログラマーであるため、ここで何が起こっているかがわかります。 fnは関数へのポインタでありpingpong、それが何であれ、の値が割り当てられます。そして、が指す関数はpingpong、単一のint値で呼び出されます42。だから、なぜ世界でそのようなギズモが必要なのか疑問に思って、あなたはこれを探しに行きpingpong、見つけます:

static int(*pingpong)(int) = bangbang;

さて、何bangbangですか?

int bangbang(int val)
{
    cout << val;
    return val+1;
}

「さて、ちょっと待ってください。ここで何が起こっているのですか?関数へのポインタを作成してからそれを呼び出す必要があるのはなぜですか?関数を呼び出すだけではないのですか?これは同じではありませんか?」

int main()
{
    bangbang(42);
}

はい、同じです。観察可能な効果は同じです。

それが本当にすべてであるかどうか疑問に思う、あなたは見る:

/*  IMPLEMENTATION NOTE
 *
 *  I use pointers-to-function to call free functions
 *  to document the difference between free functions
 *  and member functions.
 */

したがって、関数へのポインタを使用している唯一の理由は、呼び出されている関数がメンバー関数ではなくフリー関数であることを示すためです。

それはあなたにとって単なる「スタイルの問題」のように見えますか?それは私には狂気のように見えるからです。

于 2012-11-13T21:27:29.197 に答える
4

ここにあなたが見つけるでしょう:

クラスメンバー名が非表示になっていない限り、クラスメンバー名を使用することは、thisポインターとクラスメンバーアクセス演算子(->)でクラスメンバー名を使用することと同じです。

于 2012-11-13T20:10:55.257 に答える
4

私はあなたがこれを逆に行うと思います。何が起こるかが正確に期待されることであることをコードが保証するようにします。

特別なことは何も起こっていないことを指摘するために、なぜ余分なコードを追加するのですか?メンバー関数のクラスメンバーへのアクセスは常に行われます。それが期待されることです。それが通常起こることではない場合は、追加情報を追加する方がはるかに良いでしょう。

このようなコードで

class Foo
{
 public:
    void setBar(int NewBar) 
    { Bar = NewBar; }

「どこBarから来たの?」と自問します。

これはクラスのセッターなので、クラスメンバー変数でない場合は何を設定しますか?!そうでなければ、ここで実際に何が起こっているのかについて多くの情報を追加する理由があります!

于 2012-11-13T21:53:40.670 に答える
3

識別子がデータメンバーであることを示すためにすでに規則を使用しているので(私がお勧めするものではありませんが)、this->ほとんどすべての場合、追加は単純に冗長です。

于 2012-11-13T20:12:52.647 に答える
3

これは明らかに主観的な質問です。this->C++-idiomaticよりもpython-idiomaticの方がはるかに多いようです。this->親テンプレートクラスの名前を処理する、先頭が必要なC++のケースはほんの一握りです。一般に、コードが適切に編成されている場合、それがメンバーまたはローカル変数であることは読者には明らかです(グローバルは避ける必要があります)。また、読み取る量を減らすと、複雑さが軽減される場合があります。さらに、オプションのスタイル(私は末尾が好きです_)を使用して、メンバー変数を示すことができます。

于 2012-11-13T20:25:38.520 に答える
2

実際には何も害はありませんが、OOの経験があるプログラマーはそれを見て、奇妙だと感じるでしょう。同様に、「ヨーダ記法」、つまりを見るのも驚くべきことif (0 == x)です。

于 2012-11-13T20:07:21.773 に答える