2009-05-26 10 views
0

私はVisual Studio 6からVisual Studio 2008に移行しており、使用しているコンポーネントの機能はSetDefaultPrinterです。Preproccessor ignore

残念ながら、同じ名前のウィンドウライブラリ関数SetDefaultPrinterがあります。そして、それに関連するマクロは私の機能を使って私の道に入りつつあります。

これは私が私の関数を呼び出す必要があり、私の回避策です:

#undef SetDefaultPrinter 
    pNova->SetDefaultPrinter(); 
#ifdef UNICODE 
#define SetDefaultPrinter SetDefaultPrinterW 
#else 
#define SetDefaultPrinter SetDefaultPrinterA 
#endif // !UNICODE 

はこの周りあまり醜い方法はありますか?また、関数の名前を変更するために外部コンポーネントを制御することはできません。

答えて

3

これはC++が名前空間を追加した理由です。あまりにも悪いWindows定義では使用できません。

別のソースモジュールでは、windows.hやその他のWindowsインクルードファイルを含めないでください。スタブ関数を生成して、クラッシュ関数を呼び出します。

void MySetDefaultPrinter(CNova * pNova) 
{ 
    pNova->SetDefaultPrinter(); 
} 
+0

残念ながら、MicrosoftはほとんどのWin32 APIがマクロになって以来、ここでは名前空間を無駄にしていました。 SetDefaultPrinterはマクロ(SetDefaultPrinterAまたはSetDefaultPrinterWへのマッピング)であり、その名前は名前空間のスコープを尊重しません。 悪いデザインとWTFの瞬間があるAPIでは、これは最大のものの1つでなければなりません。残念ながら、私たちはそれに固執しているようです。 – jalf

+0

@jalf - 完全に合意しました。私はそれがWindows APIを完全にC互換に保つという要件から生まれたものだと考えていますが、関係する妥協は本当に残念です。ヘッダーには、C++用とC用の2つのセクションが必要です。 –

1

外部コンポーネントの周りにラッパーを使用できます。これは"Adapter" patternと呼ばれることもあります。

// header file 
class NovaWrapper 
{ 
    Nova *_nova; 
    public: 
    void setDefaultPrinter(); 
}; 

// implementation file - this file does not include windows.h - you need to make sure it 
// does not have visibility of the "bad" SetDefaultPrinter macro 
void NovaWrapper::setDefaultPrinter() 
{ 
    _nova->SetDefaultPrinter(); 
} 

ここで、クライアントコードを変更して、基になるインスタンスではなくNovaWrapperを使用します。

0

これは、最終的にはインクルードの順番を入れ替えるだけで解決しました。どうやら、このコンポーネントの開発者は私の前で問題を認識していたので、コンポーネントにはSetDefaultPrinterのエイリアスだけであるSetDefaultPrinterASetDefaultPrinterWが含まれていました。したがって、windows.hが関数の名前を変更しても、それは問題ではありません。