24

全体で次の構成を使用する大規模なコード ベースを扱っています。

class MyClass
{
public:
  void f(int x);
private:
  int x;
};


void MyClass::f(int x)
{
'
'
  this->x = x;
'
'
}

個人的には、私はいつも使用していたので、フォームを好みます

class MyClass
{
public:
  void f(int x);
private:
  int _x;
};


void MyClass::f(int x)
{
'
'
  _x = x;
'
'
}

私が後者を好む理由は、それがより簡潔である (コードが少ない = 潜在的なバグが少ない) ことと、同じ名前の複数の変数をスコープ内に同時に持つのが好きではないためです。とはいえ、最近は前者の使い方をよく見かけるようになりました。私が気付いていない2番目のアプローチの利点はありますか? (たとえば、コンパイル時間への影響、テンプレート化されたコードでの使用など...) いずれかのアプローチの利点は、もう一方のリファクタリングに十分な価値がありますか? 私が尋ねる理由は、コードに存在する 2 番目のアプローチは好きではありませんが、労力の量と、さらにバグを導入するという関連するリスクを考慮すると、リファクタリングに値するものではないからです。

4

15 に答える 15

27

あなたのバージョンは少しすっきりしていますが、あなたがそれをしている間、私はこうします:

  1. アンダースコアを先導することは避けてください。_xは、誰かが予約名である_MyFieldを選択するまでは問題ありません。変数名として、最初の下線とそれに続く大文字は使用できません。参照:C ++識別子でアンダースコアを使用する際の規則は何ですか?
  2. 属性をプライベートまたは保護します。コンパイルすれば変更は安全であり、セッターが確実に使用されるようになります。
  3. this->ストーリーは、たとえばテンプレート化されたコードで、フィールド名をタイプに依存させるために使用されます(ルックアップの問題を解決できます)。

明示的なthis->(g ++ 3.4.3でテスト済み)を使用して修正された名前解決の小さな例:

#include <iostream>
#include <ostream>

class A
{
public:
  int g_;
  A() : g_(1) {}
  const char* f() { return __FUNCTION__; }
};

const char* f() { return __FUNCTION__; }
int g_ = -1;

template < typename Base >
struct Derived : public Base
{
  void print_conflicts()
  {
    std::cout << f() << std::endl; // Calls ::f()
    std::cout << this->f() << std::endl; // Calls A::f()
    std::cout << g_ << std::endl; // Prints global g_
    std::cout << this->g_ << std::endl; // Prints A::g_
  }
};

int main(int argc, char* argv[])
{
   Derived< A >().print_conflicts();
   return EXIT_SUCCESS;
}
于 2009-06-29T09:43:47.777 に答える
10

フィールドの命名は、コードの臭いとは何の関係もありません。ニールが言ったように、フィールドの可視性はここで唯一のコードの臭いです。

C++の命名規則に関するさまざまな記事があります。

于 2009-06-29T09:47:30.810 に答える
4

この「this」の使用は、Microsoft C#コーディング標準によって推奨されています。これにより、コードが明確になり、メンバー変数でのm_や_などの使用法の標準となることが意図されています。

正直なところ、私はとにかく名前のアンダースコアが本当に嫌いです。以前は、すべてのメンバーの前に1つの「m」を付けていました。

于 2009-06-29T09:42:42.270 に答える
3

IDEで現在のクラスの識別子のリストがポップアップ表示されるため、多くの人がこれを使用します。

私はBCBでやっていることを知っています。

名前の競合で提供する例は例外だと思います。ただし、Delphiでは、スタイルガイドラインでは、これを正確に回避するために、パラメータにプレフィックス(通常は「a」)を使用しています。

于 2009-06-29T09:49:36.283 に答える
3

私の個人的な感覚では、既存のコーディング規約と戦うことはすべきではないということです。Sutter/Alexandrescu が彼らの著書「C++ コーディング規約」に書いているように、細かいことは気にしないでください。先頭に 'this->' や '_' などがあるかどうかに関係なく、誰でもどちらか一方を読み取ることができます。

ただし、命名規則の一貫性は通常必要とされるものであるため、ある範囲 (少なくともファイル スコープ、理想的にはコード ベース全体) で 1 つの規則に固執することは、良い習慣と見なされます。このスタイルはより大きなコード ベース全体で使用されているとおっしゃっていたので、別の規則を後付けするのはかなり悪い考えだと思います。

結局のところ、変更する正当な理由があることがわかった場合は、手動で変更しないでください。最良の場合、IDE はこの種の「リファクタリング」をサポートします。それ以外の場合は、変更するためのスクリプトを作成します。検索と置換は最後のオプションです。いずれにせよ、バックアップ (ソース管理) とある種の自動テスト機能が必要です。そうしないと楽しめません。

于 2009-06-30T08:00:46.893 に答える
2

このように 'this' を使用することは、IMO のコードの匂いではなく、単なる個人的な好みです。したがって、システム内の残りのコードとの一貫性ほど重要ではありません。このコードに一貫性がない場合は、他のコードと一致するように変更できます。それを変更することによって残りのコードの大部分との矛盾が生じる場合、それは非常に悪いことであり、私はそのままにしておきます。

コード テニスをプレイする立場にはなりたくありません。誰かが純粋に「見栄えを良くする」ためだけに何かを変更し、後で別の誰かが別の好みでやって来て、それを元に戻します。

于 2009-06-29T11:28:02.840 に答える
1

私は常にm_命名規則を使用しています。私は一般的に「ハンガリー語表記」が嫌いですが、クラス メンバー データを扱う場合、非常に明確に表示されると非常に便利です。また、同じスコープで 2 つの同一の変数名を使用すると、エラーが発生しやすいことがわかりました。

于 2009-06-29T09:39:33.620 に答える
0

class MyClass{
public:  
  int x;  
  void f(int xval);
};
//
void MyClass::f(int xval){  
  x = xval;
}
于 2009-06-29T09:39:41.560 に答える
0

私の意見では、これはコードを乱雑にする傾向があるので、異なる変数名を使用する傾向があります(規則によっては、アンダースコア、m_など)。

于 2009-06-29T09:42:04.597 に答える
0

現在、ほとんどの IDE エディターは変数に色を付けて、ローカル変数のクラス メンバーを示しています。したがって、IMO では、読みやすさのためにプレフィックスも 'this->' も必要ありません。

于 2015-06-29T12:01:50.667 に答える
0

同意します。私はその命名規則が好きではありません - 私はメンバー変数とローカル変数の間に明らかな違いがあるものを好みます。を放置するとどうなりますthisか?

于 2009-06-29T09:38:10.300 に答える
0

私は「これ」を使うのは好きではありません。古き良き C (C を覚えていますか?) でプログラミングしていて、OOP の特性の一部を模倣したい場合は、いくつかのメンバーを持つ構造体を作成し (これらはオブジェクトのプロパティに類似しています)、セットを作成します。その構造体へのポインターをすべて最初の引数として取る関数 (これらは、そのオブジェクトのメソッドに類似しています)。

(この typedef 構文は正しいと思いますが、しばらく経ちました...)

typedef struct _myclass
{
   int _x;
} MyClass;

void f(MyClass this, int x)
{
   this->_x = x;
}

実際、古い C++ コンパイラは実際にコードを上記の形式にコンパイルし、それを C コンパイラに渡すだけだったと思います。言い換えれば、C++ はある程度、シンタックス シュガーに過ぎませんでした。したがって、C++ でプログラミングし、コードで「this」を明示的に使用する方法に戻りたいと思う人がいる理由はわかりません。おそらく、「構文的ニュートリスウィート」です。

于 2009-06-29T15:03:38.143 に答える
0

C++ では、初期化子を使用して構築時にメンバーを初期化するのがより一般的です。

そのためには、メンバー変数の名前とは異なる名前を使用する必要があります。

したがってFoo(int x) { this.x = x; }、Java で使用したとしても、C++ では使用しません。

本当の匂いは、それ自体の使用ではなく、メンバー変数を変更する以外に何もしない初期化子とメソッドの使用の欠如かもしれませんthis -> x

初期化子を使用する場合、メンバー変数へのコンストラクター引数に異なる名前を使用することが、私が行ったすべての C++ ショップで普遍的な慣行である理由を誰でも知っていますか? それをサポートしていない C++ コンパイラがいくつかありましたか?

于 2009-06-29T09:50:23.270 に答える
0
class MyClass
{
public:
  int m_x;
  void f(int p_x);
};


void MyClass::f(int p_x)
{
  m_x = p_x;
}

...スコーププレフィックスを使用する私の好みの方法です。メンバーには m_、パラメーターには p_ (代わりに引数に a_ を使用するものもあります)、グローバルには g_、読みやすさに役立つ場合はローカルには l_ を使用することもあります。

同じ名前に値する 2 つの変数がある場合、これは非常に役立ち、再定義を避けるためだけにその意味をランダムに変更する必要がなくなります。さらに悪いことに、恐ろしい「x2、x3、x4など」...

于 2009-06-29T09:51:08.090 に答える
-2

命名規則に問題がある場合は、次のようなものを使用してみてください。

class tea
{
public:
    int cup;
    int spoon;
    tea(int cups, int spoons);
};

また

class tea
{
public:
    int cup;
    int spoon;
    tea(int drink, int sugar);
};

私はあなたがアイデアを得たと思います。基本的に、変数に異なる名前を付けていますが、論理的な意味では「同じ」です。お役に立てば幸いです。

于 2009-06-29T10:01:40.657 に答える