ヘッダーファイルで関数の定義

ヘッダーファイルだけで関数を定義したいときがありますが、定義の仕方によってはリンクエラーになるので、そのときの挙動についてまとめました。

extern(外部リンゲージ)

各ソースファイルに関数が定義されるので、同じ関数が複数のファイルに存在することになりリンク時にエラーになる。※externのついていない関数はデフォルトでexternになる

void func()
{
}
static(内部リンゲージ)

各ソースファイルにstaticとして関数が定義されるので、エラーにはならないが同じ関数がいくつもできてしまう

static void func()
{
}

どうせヘッダーで関数を定義するなら、inlineの方が効率がよいです。

extern inline

externでインライン化すると、もしインライン化されなかった場合に上記のexternと同様にリンクエラーになる可能性がある

inline void func()
{
}
extern inline void func()
{
}
static inline

各ソースファイルにインライン化。もしインライン化されなくても各ソースファイルにstaticな関数ができるだけ

static inline void func()
{
}
変数について

変数の挙動についても関数のときと同様ですが、ヘッダーで外部リンゲージを持つexternの変数が複数のソースファイルに展開されるとリンクエラーになるので、実体を作らずに宣言だけならよい。そしてstaticだとそれぞれincludeしたファイルで展開されるのでリンクエラーにはならないが各ファイルに実体ができるので共通して利用することはできません。使うならstatic constとして定数として使えばOKです。

int GLOBAL_VAL = 123;  // 複数のファイルで展開されるとリンクエラー
extern int GLOBAL_VAL;  // 宣言だけならOK
static int GLOBAL_VAL = 123;  // 各ファイルに展開される
static const int GLOBAL_VAL = 123;  // 単なる定数
まとめ

関数をヘッダーで定義したい場合はstatic inlineで定義し、externな関数は宣言のみとします。

  • externの関数・変数宣言
  • static inlineの関数定義
  • static constな変数(定数)定義