3

今回は VS2010 で作業しているプロジェクトの 1 つをコンパイルしていましたが、windows.h のインクルードの 1 つに、既にあるコードの export const 文字列と衝突する typedef INPUT があることがわかりました。

//winuser.h (行: 5332)

typedef struct tagINPUT {
    DWORD   type;

    union
    {
        MOUSEINPUT      mi;
        KEYBDINPUT      ki;
        HARDWAREINPUT   hi;
    };
} INPUT, *PINPUT, FAR* LPINPUT;

//foo.h

//stuff here
extern FOO_DLL_API const string INPUT;

今、私は問題のある .cpp で INPUT を使用せず (そして私はほとんどのコードを所有していません)、影響を最小限に抑えようとして、次のことを行いました。

//myfile.cpp

#include <foo.h>
namespace windowsLib {    //I added this
#  include <windows.h>
}

using namespace windowsLib;

これまでのところ、このアプローチはうまく機能していますが、このアプローチに潜在的な問題があるかどうか、またはより良い提案があるかどうかを尋ねたいと思います.

編集:

これが悪い考えである理由についてのすべてのコメントと説明に感謝します。あなたのコメントから得たのは、foo.h を変更して内容を名前空間に入れる必要があるということです。ただし、それを行うと、名前空間の修飾が必要になる数十個のファイルに影響を与えることになります。

これらすべてのファイルに触れることなく、これを「正しい方法」で行う方法はありますか?

私がコードの所有者だったら、この変更を行って完了しますが、解決策を提案し、それを承認して誰かに割り当ててもらう必要があります。したがって、変更が最小限であれば簡単です。

編集2:

私の最終的な提案は、次のようにクラスを 2 つに分割することでした。

//stub.cpp

#include <windows.h>

//Implementation of wrapper methods

//stub.h

class stub {
    //public wrapper methods
}

//myfile.cpp

#include <stub.h>
#include <foo.h>    

その提案は、現在直面している現在の最小限の影響の制約の問題も解決するため、Benlitz の回答を受け入れています。しかしながら、皆様のコメントに感謝いたします。

4

4 に答える 4

3

言語で許可されていないだけでなく (標準ヘッダーが名前空間内に含まれると仮定して)、 で宣言された関数<windows.h>呼び出すと、リンカーが名前空間でそれらを検索することが判明するという問題もありますwindowsLib

うまくいきません!

于 2012-05-15T20:02:34.173 に答える
2

これは少なくとも悪い考えのようです。

1)それが実際にあなたのコードである場合using namespace windowsLib;、次の行に名前空間があるため、名前空間を追加してもメリットはありません。INPUTとにかく曖昧ではないですか?

2)からのものを使用し、正しいシンボルを使用しない他のヘッダーを含めることができます。windows.hを返す関数を定義するヘッダーを含めることを想像してくださいINPUT。どうやってうまくいくの?

安全にプレイして、タイプの名前を変更することをお勧めします。

于 2012-05-15T19:58:31.153 に答える
1

他の回答で説明されているように、それは悪い考えです。問題の解決に役立つ可能性のあるアイデアを次に示します。

//myfile.cpp

#define INPUT UnusedSymbol
#include "foo.h"
#undef INPUT

#include "windows.h"

INPUT は foo.h の extern 変数であるため、これは機能する可能性があります。そのため、myfile.cpp で使用しない限り、コンパイラもリンカーも気にしません。UnusedSymbol はダミーの名前です。ソースで使用されていない名前を記述できます。

于 2012-05-15T20:12:38.880 に答える
1

windows.h の周りに名前空間を配置するのは危険に思えます。それはおそらくあなたが必要とするものを隠すでしょう。とにかく次の行で名前空間をインポートすることを除いて。

名前空間を foo.h の周りに置きます。

namespace fooLib {
#include "foo.h"
}

using fooLib;

これは問題をOSコードからfooコードに移すだけだと思いますが、それは私にとってより安全に思えます。

もう 1 つの方法は、foo 関数を呼び出して foo グローバルを返す foo のラッパーを別の小さなラッパー ライブラリに構築することです。windows.h を必要としないもの。このラッパーを名前空間に配置して、これが再び発生するのを防ぎます。

ここでは、名前を変更したり、 foo.h 内のものの周りに名前空間を配置したりする能力がないことを前提としています。foo.hfooLib

触れることができる場合はfoo.h、foo.h の INPUT の名前を変更するか、foo.h のものを独自の名前空間に配置することをお勧めします。fooLib名前空間には大きな (明らかな) メリットがあると思います。

于 2012-05-15T20:16:29.727 に答える