「#define me(* this)」をお勧めしますか?


19

このマクロは、コンパイラのコマンドラインパラメーターとして、グローバルヘッダーで定義することができます。

#define me (*this)

そして、いくつかの使用例:

some_header.h:

inline void Update()
{
    /* ... */
}

main.cpp:

#include "some_header.h"

class A {
public:
    void SetX(int x)
    {
        me.x = x;   
        me.Update(); 
    }

    void SomeOtherFunction()
    {
        ::Update();
    }

    /*
        100 or more lines
        ... 
    */

    void Update()
    {
        // ... 
    }

    int x;  
};

したがって、クラスメンバーにアクセスするときのクラスメソッドでは、常にを使用しme、グローバル識別子にアクセスするときには常に使用します::。これにより、コードに精通していない読者(おそらく数か月後には自分自身)に、他の場所を探す必要なくアクセスされたもののローカライズされた情報が提供されます。どこでもme使用this->するとうるさくてugいため、定義したいです。しかし#define me (*this)、C ++の優れた実践と考えることができますか?meマクロにはいくつかの実用的な問題点がありますか?また、C ++プログラマとして、meマクロを使用するコードの読者になる場合、それを好むか好まないのでしょうか?

編集:多くの人meがを使用して具体的に反論するのではなく、一般的にこれを明示的に反論するため。「どこでもこれを明示する」ことの利点が何であるかは明確ではないと思う。

「どこでもこれを明示する」ことの利点は何ですか?

  • コードの読者として、アクセスされるものに確実性があり、検証することとは異なることに集中することができます。
  • より具体的に検索機能を使用できます。「検索this->x」のみ検索するよりも、あなたに多くの望んでいた結果を与えることができます「x
  • あるメンバーを削除または名前変更するとき、コンパイラーはこのメンバーが使用されている場所で確実に通知します。(一部のグローバル関数は同じ名前を持ち、明示的なthisを使用していない場合にエラーが発生する可能性があります)。
  • コードをリファクタリングし、メンバーから非メンバー関数を明示的に作成すると(カプセル化を改善するため)、編集する必要がある場所が示され、非メンバー関数パラメーターとして指定されたクラスのインスタンスへのポインターに簡単に置き換えることができます
  • 一般に、コードを変更するときは、明示的なthisをどこでも使用するときよりも、明示的なthisを使用しないときのエラーの可能性が高くなります。
  • 明示的にこれは、外部からメンバーにアクセスしているときの明示的な「m_」よりもノイズが少ない(object.membervs object.m_member)(この点を見つける@Kazに感謝)
  • 明示的にこれは、すべてのメンバー(属性とメソッド)の問題を普遍的に解決しますが、「m_」または他のプレフィックスは属性に対してのみ実用的に使用できます。

このリストを洗練して拡張し、他の利点について知っているかどうか、そしてどこでも明示的なthisのユースケースを教えてください。


3
関数の引数とメンバーが同じ名前になることを避け、明示的な「this」を避ける必要があります。
pjc50

4
上司のVBコードを思い出させます。どこでも私。利己的ですね。:pとにかく、これまでの答えはすべてを言っています。
MetalMikester

19
それは素晴らしいアイデアです!そして、Pythonのバックグラウンドから来た人のために、なぜ#define self (*this)ですか?両方のマクロ混在させて、 VBとPythonを模倣したファイルを作成することもできます。:)
logc

11
理由だけではなく、すべてを出て行く、としない:#include "vb.h"#Include pascal.h、または#include FOTRAN.h、あなたのコードがそれを提出触れる隣の人持ってTDWTFを
ダンニーリー

4
ああ、お願いします。属性をとして宣言するだけで、トラブルを軽減できますme_x
ロボット

回答:


90

いいえそうではありません。

あなたがより環境に優しい放牧地を離れてから数年後にあなたのコードを維持し、使用する言語の一般的な慣習に従うプログラマーに注意してください。C ++では、thisクラスはシンボル解決の順序に含まれており、クラススコープでシンボルが見つかった場合this->は暗黙的に示されるため、ほとんど記述する必要はありません。だから、みんながするように書いてはいけない。

クラススコープからのシンボルが混乱することがよくある場合、通常のアプローチでは、メンバー(フィールドおよび場合によってはプライベートメソッド。パブリックメソッドに使用されることはありません)に共通の命名パターンを使用します。一般的なものは、と接尾辞を付ける含める_かを前に置きますm_m


12
「C ++では、これを記述する必要はほとんどありません」これは、質問とはまったく関係のない規則です。一部の人々(私のような)thisは、変数がメソッドに対してローカルではないことを明示的に明確にするために書くことを好みます。ここでの質問は、マクロmeが存在すべきかどうかであり、使用すべきthisものかどうかではありません。
Mehrdad

8
@Mehrdad:OPがのme.代わりに使用していると明示的に述べているためthis->。必要this->がないのでme.、マクロは必要なく、したがってマクロも必要ありません。
マーティンヨーク

11
@LokiAstari:質問のなかには、OPがthis->「必要か」という疑問をリモートで示唆するものすらありません。実際、OPはthis->、それが必要ではないという事実にもかかわらず使用していると言います。問題は、の代わりにをme.使用すべきかどうかであり this->、この回答では実際に回答されません。
Mehrdad 14

4
@Mehrdad:しかし、yesまたはnoを入力するだけで、非常に退屈な答えになります。したがって、説明は通常、回答に到達する方法を説明するのに非常に役立ちます(回答方法で推奨されます)。結論は使用することではありません。なぜなら、OPは使用に関して最初から間違った態度を持っているthisため、完全にバランスのとれた結論を達成するためには、その点に関する議論が必要です。
マーティンヨーク14

1
理由を説明するために+1。「いいえ、悪い習慣だ」と言うのではなく。
user253751 14

42

そのため、新しい言語を作成します。次に、そうし、C ++に障害を与えないでください。

しない理由はいくつかあります。

  1. すべての通常のコーディング標準は、マクロを避けることを提案します(ここに理由があります
  2. そのようなマクロを使用してコードを維持することは困難です。C ++でプログラミングしている人thisは誰でも知っており、そのようなマクロを追加することで、実際に新しいキーワードを追加しています。みんなが好きなものを紹介したらどうでしょうか?コードはどのように見えるでしょうか?
  3. いくつかの特別な場合を除き、使用しない(*this).this->、まったく使用しないでください(この回答を参照して「this->」を検索してください)

あなたのコードは#define R return、実際のコードで見たとは違いません。理由?タイピングが少ない!


オフトピック少し行くが、ここで私は(使用していない点3に拡大するつもりです(*this).this->クラスで)。

まず第一に、(*this).またはthis->オブジェクトのアクセスメンバ変数や関数に使用されています。それを使用することは無意味であり、より多くの入力を意味します。また、テキストが多いため、このようなコードの読み取りはより困難です。つまり、メンテナンスが難しくなります。

だから、あなたが使用しなければならないケースは何this->ですか?

(a)残念ながら引数名の選択。

この例でthis->は、引数がメンバー変数と同じ名前であるため、が必要です。

struct A {
  int v;
  void foo( int v ) {
    this->v =v;
  }
};

(b)は、テンプレートと継承を扱う場合(参照これを

この例は、コンパイラがvアクセスする変数の名前を知らないため、コンパイルに失敗します。

template< typename T >
struct A {
  A(const T& vValue):v(vValue){}

  T v;
};

template< typename T >
struct B : A<T>
{
    B(const T& vValue):A<T>(vValue){}

    void foo( const T & newV ) {
      v = newV;
    }
};

1
「だから、新しい言語を作成したい。そうすれば、c ++を損なうことはない」- 同意しません。CとC ++の主な強みは柔軟性です。OPはC ++を不自由にすることはなく、その柔軟性を特定の方法で利用するだけで、コーディングが容易になります。
user253751 14

2
@immibisそうです。彼にとって簡単なことは、他の人にとっては難しいことです。チームで作業するとき、コードにそのようなナンセンスを入れても、あまり有利にはなりません。
BЈовић

2
あなたの答えは「定義は悪」と変わりません。
ミスターリスター14

7
@MrLister私の答えは「愚かな定義は悪」です。質問のマクロは使用するのが愚かで、私が示したように、まったく必要ありません。コードが良いとさらに良いのないです*this.し、this->
BЈовић

1
@Mehrdadまだメンバー変数にプレフィックスとサフィックスを追加していますか?私はそれがClean Codeのような本で「修正された」と思った。pre-c ++ 11 this->と同じくらい便利ですauto。つまり、コードノイズが増加するだけです。
BЈовић

26

これをしないことをお勧めします。これにより、マクロをよく知らない読者は、これを見るたびに大きな「WTF」を得ることができます。一般に受け入れられている規則よりも「新しい規則」を発明する場合、実際の必要なしにコードは読みやすくなりません。

これを使用する->どこでもうるさくていです

それは、おそらくあなたがキーワードme(Visual Basic、私は推測する?)を使用して言語で多くのプログラミングをしたために、あなたにそう見えるかもしれません。しかし実際には、それに慣れるだけの問題です- this->かなり短く、経験豊富なC ++プログラマのほとんどがあなたの意見に同意しないと思います。また、上記の場合、使用も使用も適切this->meはありません。メンバー関数内のデータメンバーにアクセスするときにこれらのキーワードを除外することで、ごちゃごちゃになりません。

プライベートメンバー変数をローカル変数と区別したい場合はm_、接頭辞として何かのリンクを追加するか、接尾辞として下線を追加します(ただし、ここでわかるよう、この規則でも多くの人にとって「うるさい」です)。


12
_接尾辞を付ける必要があります。接頭辞として、標準ライブラリおよびベンダー拡張の内部シンボル用に予約されています。
Jan Hudec

4
@JanHudec __(2つのアンダースコア)で始まるか、アンダースコアの後に大文字が続く場合のみ。単一のアンダースコアとそれに続く小文字は、グローバル名前空間にない限り問題ありません。
エリックフィン

1
@EricFinn:2つのルールを1つに組み合わせました。2つのアンダースコアまたはアンダースコアとそれに続く大文字は内部シンボル用であり、単一のアンダースコアと小文字に続くものはシステム固有の拡張用です。アプリケーションでも使用しないでください。
1月Hudec

@JanHudecは、システム固有の拡張機能のルールを認識していませんでした。ただし、以前のコメントを残して、コメントのコンテキストを提供します。
エリックフィン

2
@JanHudec:小文字はシステム固有の拡張用ですか?これを示すC ++標準の一部への参照を投稿できますか?
Mehrdad

18

しないでください!入力を節約するためにマクロがいたるところにある大規模なコードベースに対処しようとしています。私にこれを再定義することの悪い点は、これがスコープ内にない/適用されない場合でも、プリプロセッサがそれをどこでも置換することです。たとえば、スタンドアロン関数の場合、同僚は私と呼ばれるローカル変数を他のどこかに持っている可能性があります。 。(s)彼はデバッグに満足できません...すべてのスコープで使用できないマクロを持つことになります。


6

いや!

誰かがあなたのトリックを知らずにそのヘッダーを#includeし、ファイル内のどこかに「me」と呼ばれる変数または関数がある場合に発生する混乱を想像してください。不可解なエラーメッセージが出力されると、それらは恐ろしく混乱します。


実際には、彼らはIDEで「私」にマウスオーバーし、定義を見る可能性が非常に高いです。
user253751 14

2
@immibis:しかし実際には、彼らは「誰がこのがらくたを書いたのですか?」:P
cHao 14

@immibis:私が働いているトップコーダーのほとんどはマウスを使用しません-遅すぎます。
JBRウィルキンソン14

実際、これをヘッダーに入れることは実際の問題です。cppファイルで使用する場合、問題はまったくありません。標準としてプラグマプッシュがある場合、ヘッダーでこれを行う方法をアドバイスしますが、そうしません。私の後に繰り返して。#definesはグローバルです。
ジョシュア
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.