問題
以下のようなコードがあり、コンパイルしてみる
# include "Main.h"
...
# pragma once
int f(int a){
...
}
# include "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!
# pragma once
inline int f(int a){
...
}
なんでかはわからないけど、なんでだろう
原因
@tenmyo さんthanks!
まず、エラーが出ているのはコンパイルではなくそのあとのリンクの時に出ていた。
確かに、#pragma onceで重複は防いでいたが、それは「コンパイル時のソースコードの重複」を防いでいただけでその後のリンク時には関係していない。
つまり、コンパイル時に生成されたmain.oとhoge.oの両方にf(int a)が定義されて、そこまではよかったけど、いざリンクするとなった時に同じ定義が出てきてエラー。と言った流れ
そこで、inlineで重複定義を許容することで解決する