定数の使用では、上記の 2 つの答えは正しいですが、#define
その使用だけに限定されません。の使用の別の例は、#define
マクロです。
マクロ
#define
マクロはプリプロセッサが利用するコードの断片であり、その点では他の宣言とまったく同じように機能します。プリプロセッサは、定義されたシンボルの発生をマクロのコードと文字通り交換します。例:
#define HELLO_MAC do{ std::cout << "Hello World" << std::endl; }while(false)
int main(int argc, char** argv)
{
HELLO_MAC;
}
HELLO_MAC
これにより、宣言したコードでシンボルが文字通り置き換えられます。定数の場合は、まったく同じことを行います。#define
したがって、定数の s は特定の種類のマクロと考えることができます。
マクロを使用すると、パラメーターを渡すこともできます。これは、コードにログ記録/例外ポリシーを適用する場合に特に便利です。例えば
#define THROW_EXCEPT( ex_type, ex_msg ) /
do{ throw ex_type( buildExString( (ex_msg), __LINE__, __FILE__ ) ); }while(false)
...
// somewhere else
THROW_EXCEPT( std::runtime_error, "Unsupported operation in current state" );
このコードにより、例外をスローしたファイルの行を全員がログに記録できるようになります。
多くの場合、マクロよりもテンプレートの方が適していますが、この例ではテンプレート関数を使用できません。これは、テンプレート関数の場所からではなく、throw の場所から関数__LINE__
と関数を使用する必要があるためです。__FILE__
マクロを使用してはいけない場所はどこですか? どこでも他のものを使用できます。マクロは、他のものと同様#define
に前処理されるため、コンパイラはそれらをまったく認識しません。HELLO_MAC
これは、またはに対して作成されたシンボルが存在しないことを意味するTHROW_EXCEPT
ため、デバッガーには表示されません。また、コンパイル エラーが発生した場合、特にマクロが長い場合は混乱を招く可能性があります。