web-dev-qa-db-ja.com

C ++インラインクラスメソッドにより未定義の参照が発生する

いずれかのクラスのメソッドをインライン化しようとすると、コンパイラエラーが発生します。 「インライン」キーワードを削除すると機能します。

簡単な例を次に示します。

main.cpp:

#include "my_class.h"

int main() {
  MyClass c;
  c.TestMethod();

  return 0;
}

my_class.h:

class MyClass {
 public:
  void TestMethod();
};

my_class.cpp:

#include "my_class.h"

inline void MyClass::TestMethod() {
}

私はコンパイルしてみます:

g++ main.cpp my_class.cpp

エラーが発生します:

main.cpp:(.text+0xd): undefined reference to `MyClass::TestMethod()'

「インライン」を削除すれば、すべてが正常です。この問題の原因は何ですか? (そしてどのようにクラスメソッドをインライン化するべきですか?それは可能ですか?)

ありがとう。

49
FrankMN

インライン関数の本体は、コンパイラーが実際に必要な場所に置き換えられるように、ヘッダー内にある必要があります。これを見てください: メンバー関数をインラインにするようコンパイラーにどのように指示しますか?

40
casablanca

規格の7.1.2/4:

インライン関数は、それが使用されるすべての翻訳単位で定義されるものとします...

TestMethodはmain.cppで使用しますが、そこでは定義されていません。

...外部リンケージがある関数が1つの翻訳単位でインラインで宣言されている場合、その関数は、それが出現するすべての翻訳単位でインラインで宣言されます。診断は必要ありません。

My_class.cppではなく、main.cppではなくTestMethodをインラインで定義(したがって宣言も)します。

この場合の修正は、次のように関数定義をヘッダーファイルに移動することです。

class MyClass {
 public:
  void TestMethod() {}
};

またはこのように:

class MyClass {
 public:
  inline void TestMethod();
};

inline void MyClass::TestMethod() {}
17
Steve Jessop

ヘッダーファイルでインライン化されていないと定義しましたが、cppファイルではインラインとして定義しようとしています。これは矛盾した定義であり、一方を他方から見つけることができません。ヘッダーは、インラインキーワードを実際に配置する場所です。

ただし、インラインキーワードはとにかくコンパイラーに対する提案のほうが多いため、削除します。本当に必要なのは、ヘッダーに浮動関数があり、コードベースに複数の定義がポップアップ表示されないようにする場合だけです。

3
wheaties