ヘッダのプロトタイプ宣言にstaticをつける
下記のようにヘッダのプロトタイプ宣言にstaticをつけるとどうなるでしょうか?
ab.h
static void g_func(void);
a.cpp
#include "ab.h" int main(void){ g_func(); return 0; }
b.cpp
#include <iostream> #include "ab.h" static void g_func(void){ std::cout << "文字出力" ; }
これはstaticの関数g_func();を呼んでいるa.cpp側で[静的関数 'void g_func(void)' が宣言されましたが定義されていません。]というコンパイルエラーとなります。staticのついた関数に関しては呼び出しがあったところでオブジェクト内部からアドレスを探してくるのがコンパイラの仕様のようです。そこでa.cpp に同名のg_func();を多重定義するとどうなるでしょうか?
a.cpp
#include "ab.h" int main(void){ g_func(); return 0; } static void g_func(void){ std::cout << "文字出力2" ; }
これがリンクエラーにもならずビルドできてしまいます。オブジェクトファイル(.obj)を見てみるとstatic付きの関数に関してはラベルが存在しないのが判ります(g_funcを検索しても見つかりません)そのままアドレスでリンクをしてしまう事が判ります。
ヘッダでstatic付きの関数プロトタイプ宣言するとこういった二重定義を許してしまう事が解りました。static付きの関数は内部結合しか許さないというメッセージでもあるのでヘッダではなく本体に定義しなければなりません。なおクラス内で定義するstaticのメソッドとはまったく意味合いが異なるので混同しないよう注意が必要です。c++のクラス内でstaticをつけるという事は実体を作らなくても関数を使用できるためむしろglobal関数としての意味合いが強くなります。