4

GetClassName() と呼ばれるメンバーを持つ C++ の動的クラス システムを持つコードがいくつかあります。ただし、Windows ヘッダーを含む大規模なプロジェクトに含めると、すべてが崩壊しました。どうやら Windows は #define GetClassName (GetClassNameA または GetClassNameW) を使用してすべてを台無しにしてしまい、仮想コール ツリーがすべて台無しになり、暗闇の中で愚かなコンパイラ デバッグで 1 日を失い、何が間違っていたのかを突き止めようとしました。

したがって、#define にこのように恐ろしく衝突しやすい名前を使用したことで Microsoft をののしっていることに加えて (正直なところ、誰かがこれのために撃たれるべきだ!)、私は 3 つの目的を求めています。

  1. GetClassName() の別の適切な名前は何ですか?
  2. とにかくこれを修正する方法はありますか?将来的には、私のコード ベースの他の開発者が同様の運命に苦しむことはありません。
  3. そして後世のために、他の誰かがこの同様に不可解なエラーに遭遇したとき
4

4 に答える 4

6
  1. ClassGetName()
  2. #undef GetClassName
  3. WinAPI は C API です。名前空間はありません。他のプラットフォームの中には、すべてのシンボル名にプレフィックスを付けることでこれを軽減しようとするものもありますが、最終的にはそれもうまくいきません。最善の策: Windows Platform SDK ヘッダーに依存しないコードを作成している場合は、それらを使用しない#includeでください。
于 2009-02-24T02:50:24.967 に答える
4

メソッドの名前を変更します。

もちろん、言うことができます

#include <windows.h>
#undef GetClassName

しかし、それはきれいではありません。自分のコードのユーザーは、win32 関数を呼び出すときに ::GetClassNameW を記述することを忘れないでください。

クラスに GetClassNameA および GetClassNameW メソッドを提供することはできますが、それは明らかに醜いものです。

名前を長くするか短くするかの2つのアプローチがあります:)

1) サブシステム内のすべての関数のプレフィックス fe TI_ (型情報用) を追加します。

TI_GetClassName() 
TI_GetBaseClass() 
TI_IsDerivedFromClass()
etc  

2)またはそれらをいくつかの IClass インターフェイスに入れます

interface IClass {
GetName();
GetBase(); 
IsDerivedFrom();
etc

単一のメソッドからそのインターフェイスを返す
ため、GetClassName() は次のようになります。

GetClass()->GetName()
于 2009-02-24T05:20:10.517 に答える
2

おそらくGetWindowClassName?実際には、GetClassName はウィンドウ クラスに関連するため、この API の悪い名前ではありません。本当の問題は、これが C API 宣言であり、C 宣言には、グローバル名前空間を汚染しない再利用可能な宣言を導入する方法がないことです。

これは、Microsoft というよりも C 言語の欠点です。

于 2009-02-24T02:51:58.660 に答える
2

Windows API には、ビルド オプションに応じて ASCII/UTF-16 を示すサフィックスが付いた関数名に展開されるクリーンな名前のマ​​クロがぎっしり詰まっています。すべてに「W32」などの接頭辞 (OS X では「NS」) を付ければよかったのですが、おそらく API を「クリーン」に保つためにそうしないことを選択しました。

API よりもコードを変更する方がはるかに簡単であるため、いくつかの提案を以下に示します。

1) Windows API を学習する (実際にはそれほど大きくありません!)、または少なくともMSDNに精通して、不可解なプログラム フローに遭遇したときに名前の衝突を探すこ​​とができるようにします。

2) (MyClass::GetClassName()) が可能な場合は、コードで明示的なスコープ解決を使用します。残念ながら、これにより仮想関数のディスパッチが中断されるため、注意してください。

3) コードで別の命名規則を使用します。MS は常に CamelCase を使用するため、他の規則 (get_class_name()、getClassName() など) を選択しても衝突しません。

4) 個人的には、ゲッターとセッターに "GetX()" と "SetX()" という名前を付けるのは嫌いですが、オーバーロード メカニズムに頼って、ゲッターには "xtype X() const" を使用し、"void X(xtype newval) 「セッター向け。あなたの走行距離は異なるかもしれませんが、私はそれがよりきれいであると思います.get/setは引数から明らかです. デフォルトの引数を使用している場合は、明らかに注意が必要です。

幸運を!

于 2009-02-24T03:03:40.737 に答える