HOWTO · C++

C++ での Class::Function()への未定義の参照

C++ での未定義の参照のリンカーエラーを解決するための簡単なチュートリアル。

このチュートリアルでは、C++ プログラミングで最も一般的で同様に重大なエラーの 1つ(つまり、Class::Function() への未定義の参照)について簡単に説明します。

最初に、C++ でコーディングする際のさまざまなエラーについて簡単に説明します。次に、未定義の参照エラーの原因と修正について説明します。

C++ のエラーの種類

C++ コードは、他のプログラミング言語と同様に、さまざまな理由でエラーやバグが発生する可能性があります。これらのエラーは、大きく次のエラーカテゴリに分類されます。

  • 構文エラーは、C++ の規則または構文の違反が原因で発生するエラーです。
  • ランタイムエラーは、構文的にプログラミングの問題がない場合に発生するエラーですが、実行時に検出され、プログラムのクラッシュにつながります。
  • 論理エラーは、目的の結果または出力が得られない場合に発生します。これは、プログラムのロジックに誤りがあることを意味します。
  • リンカーエラーは、プログラムが正常にコンパイルされ、他のオブジェクトをメインオブジェクトファイルにリンクしようとしているため、実行可能ファイルが生成されない場合のエラーの種類です。たとえば、定義された関数の間違ったプロトタイプ、含まれている間違ったヘッダーファイルなど。

C++ での Class::Function() への未定義の参照

これは C++ で最も頻繁に発生するエラーであり、特に新しいプログラマーにとっても同様に重要です。このタイプのリンカエラーは、プログラムの実行に影響を与える可能性があります。

これらのエラーは主に、プログラムが正常にコンパイルされ、他のオブジェクトファイルをメインオブジェクトにリンクしようとしているリンクフェーズにある場合に発生します。プログラムが出力を出す場合があり、このエラーが発生します。

そのため、このようなエラーを追跡して修正するのは複雑な場合があります。

未定義の参照エラーは、クラス、関数、または変数への参照を使用したときに発生します。リンカは、リンクされたすべてのオブジェクトファイルとライブラリでその定義を見つけることができないため、Undefined Reference to a Class::Function() というエラーが生成されます。

これらのエラーにはいくつかの原因が考えられますが、ここでそれらのいくつかについて説明します。

C++ に関数定義がないため、Class::Function() への未定義の参照を解決する

これは、関数のプロトタイプを提供したが、その定義を与えるのを忘れたという、このエラーの最も簡単な理由である可能性があります。

その関数の参照を作成すると、リンカはその定義を見つけることができず、Undefined Reference to a Class::Function() というエラーが生成されます。

これは、以下の例で示されています。

#include <iostream>
class Square {
 public:
  double length;  // Length of a box
  double width;   // Breadth of a box
  double height;  // Height of a box

  double getArea(void);
};
int main() {
  Square sq1;
  sq1.getArea();
  return 0;
}

出力:

(.text+0x15): undefined reference to Square::getArea()
collect2.exe: error: ld returned 1 exit status

C++ でオブジェクトファイルがリンクされていないために Class::Function() への未定義の参照を解決する

別のファイルを使用してクラスを定義する場合、プログラムをリンクするときにメインオブジェクトファイルとリンクするメイン関数ファイルにそのファイルを含める必要があります。

以下の例では、Square クラスを別のファイルで個別に定義しました。メインファイルでは、そのオブジェクトを参照しているため、ファイルがリンクされていないため、未定義の参照エラーが発生します。

例:

#include <iostream>
using namespace std;

int main() {
  Square sq1;
  cout << sq1.getArea();
  return 0;
}

例(Square.cpp):

class Square {
 public:
  double length;  // Length of a box
  double width;   // Breadth of a box
  double height;  // Height of a box
  double getArea(void) { return length * width; }
  void setLength(double l) { length = l; }
};

この問題の解決策は、次のコードで Square.cpp ファイルをメインファイルにリンクすることです。

#include <iostream>

#include "square.cpp"
using namespace std;

int main() {
  Square sq1;
  cout << sq1.getArea();
  return 0;
}

C++ で依存ファイルがコンパイルされていないために Class::Function() への未定義の参照を解決する

このタイプのエラーは、プログラムのすべての依存関係が正常にコンパイルされていない場合にも発生します。リンカが実行可能ファイルを正常に生成するには、リンクフェーズを開始する前にすべての依存関係をコンパイルする必要があります。

これは、リンカがすべての依存オブジェクトファイル(つまり、.o ファイル)を簡単に見つけられるようにするために避けられません。依存オブジェクトファイルが見つからない場合、リンカは未定義の参照エラーを生成します。

ノート
GNU の g++ コンパイラを使用する場合、Bash コマンド g++ -c abc.cpp は、リンカーを呼び出さずに、対応するオブジェクトファイル abc.o を生成します。

上記の状況とは別に、未定義の参照エラーには他の多くの状況が存在する可能性があります。このような問題を回避するには、プログラマーはすべての識別子(関数、変数、オブジェクトなど)を正しく定義する必要があります。