C言語・C++ではプロトタイプ宣言を行って定義しておき、別のソースファイルやファイルの後ろの方で実装することがよくあります。
void f(int);
int main() {
f(1);
}
int f(int a) {
return a * 2;
};
上記のようなコードです。C言語では可読性のことも考慮して宣言と実装を分けて書くことが一般的です。
ですが、プロトタイプ宣言とは別で書いているにも関わらず、いざ関数を呼び出すと関数が実装されていないことを示すLNK2019「未解決シンボルが〇〇で参照されました」のエラーが表示されてコンパイルできないことがあります。
この記事では、プロトタイプ宣言と関数の実装を行ったはずなのに「未解決シンボルが〇〇で参照されました」が表示されてしまう原因と対処法解説します。
LNK2019「未解決シンボルが〇〇で参照されました」とは?
「未解決シンボルが〇〇で参照されました」とは、プロトタイプ宣言として関数が定義されているものの、関数の実装がない状態で関数を呼び出したときに発生するエラーです。
例えば以下のコードはfunc関数がプロトタイプ宣言されていますが、func関数の処理が実装されていない状態で呼び出すとしているためLNK2019「未解決シンボルが〇〇で参照されました」が表示されます。
void func(int);
int main() {
func(1);
}
この場合は、LNK2019コード「未解決シンボルが〇〇で参照されました」が表示されてコンパイルに失敗します。
LNK2019エラーが発生する場合、未解決シンボル数を表すLNK1120コードも同時に発行されます。
LNK2019「未解決シンボルが〇〇で参照されました」の対処方法
LNK2019「未解決シンボルが〇〇で参照されました」が起きる原因は、どこかでプロトタイプ宣言されているけど関数が実装されていない状態で関数を呼び出そうとしたときに発生するエラーです。
ですので呼び出そうとして関数を実装してあげればエラーは解消されます。
関数が実装されていたら問題ないので、処理がreturn 0;
だけの関数でも問題ありません
関数を実装したのに「未解決シンボルが〇〇で参照されました」が表示される
関数を実装したのに「未解決シンボルが〇〇で参照されました」が表示されてしまうことがあります。これはコンパイラーのバグではなく必ずソースコードに何かしらの問題があります。
よくあるのが以下の間違いです。
プロトタイプ宣言時の仮引数と実装時の引数を間違えている
例えばプロトタイプ宣言ではfloat型の引数を指定しているものの、実装箇所ではdouble型として定義しているときです。
//float型
int func(float);
int main() {
func(1.4);
}
//double型になっている
int func(double a) {
return a * 2;
};
引数が異なる同名の関数は別物として扱われるため、関数が実装されていない扱いになり「未解決シンボルが〇〇で参照されました」が表示されることがあります。
結構見落としがちな問題で知らないとエラーを直すまでに時間がかかってしまうので、引数の型にはよく注意するようにしてください。
関数名のスペルミスにも注意
当然ですが、1文字でも関数名が異なれば違う関数として扱われます。
可能な限りヒューマンエラーを減らしたいのであればプロトタイプ宣言部分の行をコピーして使うといいでしょう。コピーペーストであればタイピングミスで違う関数名になってしまうことを防げます。