いくつかのコードを調べたところ、規則はポインター型を次のように変換することであることに気付きました
SomeStruct*
の中へ
typedef SomeStruct* pSomeStruct;
これにメリットはありますか?
いくつかのコードを調べたところ、規則はポインター型を次のように変換することであることに気付きました
SomeStruct*
の中へ
typedef SomeStruct* pSomeStruct;
これにメリットはありますか?
これは、ポインター自体が「ブラック ボックス」、つまり、内部表現がコードに関係のないデータの一部と見なされる場合に適しています。
基本的に、コードがポインターを逆参照せず、API 関数に渡すだけの場合 (場合によっては参照によって)、typedef は*
コード内の s の数を減らすだけでなく、ポインターを逆参照する必要があることをプログラマーに示唆します。本当に干渉しないでください。
これにより、必要が生じた場合に将来 API を変更することも容易になります。たとえば、ポインターではなく ID を使用するように変更した場合 (またはその逆の場合)、既存のコードは壊れません。
私の経験ではありません。「 」を非表示に*
すると、コードが読みにくくなります。
typedef 内でポインターを使用するのは、関数へのポインターを扱うときだけです。
typedef void (*SigCatcher(int, void (*)(int)))(int);
typedef void (*SigCatcher)(int);
SigCatcher old = signal(SIGINT, SIG_IGN);
そうでなければ、それらは役立つというよりも混乱を招くと思います。
signal()
、シグナル キャッチャーではなく、関数へのポインターの正しい型です。SigCatcher
次のように書くことで、(上記の修正されたタイプを使用して)より明確にすることができます。
typedef SigCatcher (*SignalFunction)(int, SigCatcher);
または、signal()
関数を宣言するには:
extern SigCatcher signal(int, SigCatcher);
つまり、 aSignalFunction
は、2 つの引数 ( anint
と a SigCatcher
) を取り、 a を返す関数へのポインターSigCatcher
です。そしてsignal()
それ自体は、2 つの引数 ( anint
と a SigCatcher
) を取り、 a を返す関数SigCatcher
です。
これにより、いくつかのエラーを回避できます。たとえば、次のコードでは:
int* pointer1, pointer2;
pointer2 はint *ではなく、単純なintです。しかし、typedef では、これは起こりません。
typedef int* pInt;
pInt pointer1, pointer2;
現在は両方ともint *です。
それは(非常に多くの答えのように)依存します。
C では、オブジェクトがポインターであることを偽装しようとしているため、これは非常に一般的です。これがすべての関数が操作するオブジェクトであることを暗示しようとしています (下のポインターであることはわかっていますが、操作しているオブジェクトを表しています)。
MYDB db = MYDBcreateDB("Plop://djdjdjjdjd");
MYDBDoSomthingWithDB(db,5,6,7);
CallLocalFuc(db); // if db is not a pointer things could be complicated.
MYDBdestroyDB(db);
MYDB の下には、おそらく何らかのオブジェクトへのポインタがあります。
C++ では、これは不要になりました。
主な理由は、参照によって物事を渡すことができ、メソッドがクラス宣言に組み込まれているためです。
MyDB db("Plop://djdjdjjdjd");
db.DoSomthingWithDB(5,6,7);
CallLocalFuc(db); // This time we can call be reference.
db.destroyDB(); // Or let the destructor handle it.
これはスタイルの問題です。この種のコードは、Windows ヘッダー ファイルで頻繁に見られます。ただし、小文字の p を前に付けるのではなく、すべて大文字のバージョンを好む傾向があります。
個人的には、この typedef の使用は避けています。PFoo よりも Foo* が欲しいとユーザーに明示的に言わせる方がはるかに明確です。Typedef は、最近では STL を読みやすくするのに最適です :)
typedef stl::map<stl::wstring,CAdapt<CComPtr<IFoo>> NameToFooMap;
Typedef はコードを読みやすくするために使用されますが、ポインターを typedef にすることは混乱を招きます。typedef ポインターは避けたほうがよいでしょう。
これを行うと、コンパイラが次のように読み取るため、const pSomeStruct の STL コンテナーを作成できなくなります。
list<const pSomeStruct> structs;
なので
list<SomeStruct * const> structs;
要素が割り当て可能でないため、これは正当な STL コンテナーではありません。
この質問を参照してください。
typedef の目的は実装の詳細を隠すことですが、ポインター プロパティを typedef すると、隠しすぎてコードが読みにくく、理解しにくくなります。ですから、そうしないでください。
実装の詳細を非表示にする場合 (多くの場合、これは良いことです)、ポインター部分を非表示にしないでください。たとえば、標準FILE
インターフェースのプロトタイプを見てみましょう:
FILE *fopen(const char *filename, const char *mode);
char *fgets(char *s, int size, FILE *stream);
ここで fopen は、何らかの構造体へのポインターFILE
を返します(実装の詳細はわかりません)。この場合、ポインターであるという事実を隠したpFILEFILE
タイプで機能する可能性があるため、これはあまり良い例ではありません。
pFILE fopen(const char *filename, const char *mode);
char *fgets(char *s, int size, pFILE stream);
ただし、直接指し示されているコンテンツをいじることがないため、それは機能します。私の経験では、いくつかの場所でコードを変更するポインタをtypedefした瞬間、非常に読みにくくなります。
Win32 API は、ほぼすべての構造 (すべてではないにしても) でこれを行います。
POINT => *LPPOINT
WNDCLASSEX => *LPWNDCLASSEX
RECT => *LPRECT
PRINT_INFO_2 => *LPPRINT_INFO_2
一貫性があるのはいいことですが、私の意見では、エレガンスは追加されません。
少し前まで、私はこの質問に「いいえ」と答えていました。現在、スマート ポインターの台頭により、ポインターは常にアスタリスク '*' で定義されるとは限りません。したがって、型がポインターであるかどうかについて明らかなことは何もありません。
だから今私は言う:それが「ポインタ型」であることが非常に明確にされている限り、ポインタをtypedefしても問題ありません。つまり、それ専用のプレフィックス/サフィックスを使用する必要があります。いいえ、たとえば、「p」は十分なプレフィックスではありません。私はおそらく「ptr」を使います。