問題
以下のようなコードがあり、コンパイルしてみる
Main.cpp
# include "Main.h"
...
Main.h
# pragma once
int f(int a){
...
}
hoge.cpp
# include "hoge.h"
...
hoge.h
# pragma once
# include "Main.h"
...
そうすると、あるエラーが。(多少パスは省略)
duplicate symbol 'f(int)' in:
.../Main.o
.../hoge.o
ld: 1 duplicate symbol for architecture x86_64
どうやら、f(int a)
がMain.hとhoge.hで二重で定義されているようだ。
...ん?
確か、しっかりとMain.hに#pragma once
はついてるが...
解決法
関数の定義にstatic
を追加したら直った(こんな感じ)
追記:
static
ではなくinline
を使った方がいいらしい。
staticは定義の区別で、inlineは重複定義の許容なので、inlineを使った方が軽くなるとのこと
@makia さんthanks!
Main.h
# pragma once
inline int f(int a){
...
}
なんでかはわからないけど、なんでだろう
原因
@tenmyo さんthanks!
まず、エラーが出ているのはコンパイルではなくそのあとのリンクの時に出ていた。
確かに、#pragma once
で重複は防いでいたが、それは「コンパイル時のソースコードの重複」を防いでいただけでその後のリンク時には関係していない。
つまり、コンパイル時に生成されたmain.o
とhoge.o
の両方にf(int a)
が定義されて、そこまではよかったけど、いざリンクするとなった時に同じ定義が出てきてエラー。と言った流れ
そこで、inline
で重複定義を許容することで解決する