関数名を取得するために、関数本体にハードコーディングされた文字列を埋め込むのは面倒で、エラーが発生しやすいため、プログラムの実行中に C99 の新しい機能を使用して関数名を取得する方法を見てみましょう。
オブジェクト リフレクション ライブラリ、デバッグ ツール、コード アナライザーは、多くの場合、実行時に関数の名前にアクセスする必要があります。最近まで、このタスクを実行する唯一の移植可能な方法は、関数本体に名前を付けて関数を手動で埋め込むことでした。言うまでもなく、このアプローチは非常に面倒で、簡単にエラーが発生する可能性があります。この記事では、新しい C99 機能を使用して実行時に関数名を取得する方法を説明します。
それでは、現在実行中の関数からプログラムで関数名を取得するにはどうすればよいでしょうか?
答えは、__FUNCTION__ と関連マクロを使用することです。
疑問の原因
多くの場合、デバッグで最もイライラするフェーズは、特定の関数が呼び出されているかどうかを常に確認することです。この問題の解決策は、通常、次のように cout または PRintf() を追加することです。C 言語を使用する場合は、次のようにします。 //その他のコード
}
通常、一般的なプロジェクトでは、そのような出力ステートメントを各関数に追加することは間違いなく困難です。そのため、これを自動的に実行できるメカニズムが必要です。
関数名を取得する
C++ プログラマーとして、__TIME__、__FILE__、__DATE__ などのマクロに遭遇することがよくあります。それらは、コンパイル時間、処理された変換単位の名前、および実行中の現在時刻を含む文字に変換されます。コンパイル文字列。
C99 として知られる最新の ISO C 標準では、別の便利なマクロのような式 __func__ が追加されており、アクセスされる関数の名前が変更されていない (つまり、切り取られていない) ことを報告します。プリプロセッサはこの関数について何も知らないため、__func__ はマクロではないことに注意してください。代わりに、暗黙的に宣言された定数文字配列として実装されます:
static const char __func__[] = "function-name";
At function-name 、実際の関数名です。この機能を有効にするには、一部のコンパイラでは特定のコンパイル フラグが必要です。具体的な情報については、対応するコンパイラのドキュメントを確認してください。
これにより、関数名を表示するための手動変更の面倒な作業のほとんどを回避できます。上記の例は次のように書き換えることができます:
void myfunc()
{
cout<<"__FUNCTION__ "<
この目的のために公式の C99 標準によって定義された __func__ 識別子は確かに注目に値しますが、ISO C++ はすべての C99 拡張機能を完全にサポートしているわけではないため、ほとんどのコンパイラーは代わりに __FUNCTION__ を使用します。 __func__ として定義されたマクロ。ほとんどの企業で広くサポートされているため、この名前が使用されます。
Visual Studio 2005 では、この機能はデフォルトで有効になっていますが、/EP および /P コンパイル オプションと一緒に使用することはできません。 IDE 環境では、__func__ は認識されないため、__FUNCTION__ に置き換える必要があることに注意してください。
Comeau ユーザーも __func__ の代わりに __FUNCTION__ を使用する必要があります。
C++ BuilderX ユーザーは、少し異なる名前、__FUNC__ を使用する必要があります。
GCC 3.0 以降は、 __func__ と __FUNCTION__ の両方をサポートします。
現在の関数名が自動的に取得できたら、次のように任意の関数名を表示する関数を定義できます:
void show_name(const char * name)
{
cout<
void myfunc()
{
show_name(__FUNCTION__); //出力: myfunc
}
void foo()
{
show_name(__FUNCTION__); //出力: foo
}
関数中括弧で囲む これは起動直後に初期化されるため、 foo() 関数と myfunc() 関数はオーバーロードを心配することなくパラメータ リストで安全に使用できます。
署名と変更された名前
__FUNCTION__ 機能は元々 C 言語用に設計されましたが、Visual Studio 2005 では、他の 2 つの非標準拡張機能もサポートされています。および __FUNCSIG__ は、それぞれ関数の変更された名前とシグネチャに変換されます。関数の名前を変更すると、たとえば 2 つのコンパイラが同じ ABI を共有しているかどうかを確認する場合に非常に役立ちます。さらに、不明瞭なリンク エラーを解決したり、C++ でリンクされた DLL から別の関数を呼び出すこともできます。 。次の例では、show_name() は関数の変更された名前を報告します。関数のシグネチャは、関数名、パラメータ リスト、戻り値の型、および含まれる名前空間で構成されます。メンバー関数の場合、そのクラス名と const/volatile 修飾子も署名の一部になります。次のコードは、独立関数と const メンバー関数のシグネチャの違いを示しています。2 つの関数の名前、戻り値の型、パラメーターはまったく同じです。 // void __cdecl myfunc(void)
}
strUCt S
{
void myfunc() const
{
show_name(__FUNCSIG__) //void __thiscall S::myfunc(void) const
}
};
上記は、C 言語で関数名の内容をプログラム的に取得するです。その他の関連記事については、PHP 中国語 Web サイト (www.php.cn) に注目してください。