HOWTO · C++

C++ での関数エラーの複数の定義を修正

この記事は、C++ での複数関数定義のエラーの解決策についてです。

この記事では、関数の複数の定義である C++ で頻繁に発生するエラーの解決策について説明します。

C++ での関数の複数の定義エラーを修正しました

このようなエラーは通常、関数のプロトタイプとその定義を分離しようとしたときに発生します。したがって、プロトタイプと定義を異なるファイルに分けて、それに応じてファイルを含めることをお勧めします。

問題を理解するために、以下の例を検討してください。

サンプルコード(file1.cpp):

// file1.cpp
#include <iostream>
using namespace std;

class classB {
  friend void f1();

 public:
  classB(int i = 1, int j = 2) : a(i), b(j) {
    cout << "Hello from constructor\n";
  }

 private:
  int a;
  int b;
  void printfun() { cout << "a=" << a << endl << "b=" << b << endl; }
};
void f1() {  // ERROR HERE
  cout << "f1 start" << endl;
  classB tmp(3, 5);
  tmp.printfun();
  cout << "f1 end" << endl;
}

サンプルコード(main.cpp):

// main.cpp
#include <iostream>

#include "file1.cpp"
using namespace std;

int main() {
  cout << "calling function" << endl;
  f1();
  cout << "exit from main" << endl;
  return 0;
}

これはあなたの状況で起こっていることです。file1.cpp ファイルには #include があるため、file1.cppmain.cpp の両方に f1() の定義が含まれており、リンカーはどちらを使用するかを認識していません。プログラムとそれについて文句を言う。

解決策は、f1() の定義を含む CPP ファイルを main.cpp から削除し、代わりに f1() の宣言を別のヘッダーファイルに含め、それを main.cpp に含めることです。コンパイラには処理する f1() の宣言があり、リンカには依存する file1.cpp からの f1() の定義が 1つだけあります。

サンプルコード(file1.h):

// file1.h
#include <iostream>

class classB {
  friend void f1();

 public:
  classB(int i = 1, int j = 2) : a(i), b(j) {
    std::cout << "Hello from constructor\n";
  }

 private:
  int a;
  int b;
  void printfun() { std::cout << "a=" << a << endl << "b=" << b << std::endl; }
};

サンプルコード(file1.cpp):

// file1.cpp
#include "file1.h"
using namespace std;
void f1() {
  cout << "f1 start" << endl;
  classB tmp(5, 6);
  tmp.printfun();
  cout << "f1 end" << endl;
}

サンプルコード(main.cpp):

// main.cpp
#include <iostream>

#include "file1.h"
using namespace std;

int main() {
  cout << "calling function" << endl;
  f1();
  cout << "exit from main" << endl;
  return 0;
}

ヘッダーファイル file1.h から始めましょう。ヘッダーファイルには、関数定義、構造またはクラス定義、定数定義などのすべての定義が含まれています。

この .h 拡張子は、このファイルをコンパイルしないことをコンパイラに通知します。テキストファイルのようなもので、誰でも読むことができます。

これは、ヘッダーファイルがドキュメントファイルであることを意味します。将来、一部の関数を使用したいプログラマーがいる場合は、関数のプロトタイプを確認するだけで、関数の定義について詳しく説明する必要はありません。

最後に、テンプレートコードもヘッダーファイルに含める必要があります。

CPP ファイルは、ヘッダーファイルで宣言された関数を定義するようになりました。これは、このファイルがコンパイルされてバイナリファイルに変換されることをコンパイラに通知します。

コードの整合性は保護され、他の誰もあなたの許可なしにコードを変更することはできません。これは、このコードの分離により、コードファイルのセキュリティも確保されることを意味します。

この手法の背後にあるもう 1つの理由は、移植性です。たとえば、後で他の多くのプログラムで使用できるバイナリ検索コードを作成しました。

関数用にこれらの個別のファイルがある場合は、他のプロジェクトでこれらの関数を簡単に使用できます。

最後に、メインファイルにはメイン関数のみが含まれ、上部にヘッダーファイルが含まれます。このファイルには、すべての関数のみを呼び出し、他には何も呼び出さない main 関数のみが含まれています。