web-dev-qa-db-fra.com

Les méthodes de classe en ligne C ++ provoquent une référence non définie

J'obtiens une erreur de compilation lorsque j'essaie d'incorporer une méthode de l'une de mes classes. Cela fonctionne lorsque je retire le mot-clé "en ligne".

Voici un exemple simplifié:

main.cpp:

#include "my_class.h"

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

  return 0;
}

ma_classe.h:

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

ma_classe.cpp:

#include "my_class.h"

inline void MyClass::TestMethod() {
}

J'essaye de compiler avec:

g++ main.cpp my_class.cpp

Je reçois l'erreur:

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

Tout va bien si je retire le "inline". Quelle est la cause de ce problème? (et comment dois-je intégrer des méthodes de classe? Est-ce possible?)

Merci.

49
FrankMN

Le corps d'une fonction en ligne doit être dans l'en-tête afin que le compilateur puisse réellement le remplacer là où cela est nécessaire. Voir ceci: Comment dites-vous au compilateur de rendre une fonction membre en ligne?

40
casablanca

7.1.2/4 de la norme:

Une fonction en ligne doit être définie dans chaque unité de traduction dans laquelle elle est utilisée ...

Vous utilisez TestMethod dans main.cpp, mais il n'y est pas défini.

... Si une fonction avec liaison externe est déclarée en ligne dans une unité de traduction, elle doit être déclarée en ligne dans toutes les unités de traduction dans lesquelles elle apparaît; aucun diagnostic n'est requis.

Vous définissez (et par conséquent déclarez également) TestMethod inline dans my_class.cpp, mais pas dans main.cpp.

Le correctif dans ce cas est de déplacer la définition de la fonction dans le fichier d'en-tête, soit comme ceci:

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

ou comme ça:

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

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

Vous l'avez défini comme non intégré dans le fichier d'en-tête, tandis que dans le fichier cpp vous essayez de le définir comme intégré. C'est une définition conflictuelle et il ne pourra pas trouver l'un dans l'autre. Votre en-tête est l'endroit où vous placez vraiment le mot clé en ligne.

Cependant, je supprimerais le mot-clé en ligne car il s'agit de toute façon d'une suggestion au compilateur. Vous n'en avez vraiment besoin que s'il y a une fonction flottante dans l'en-tête et que vous ne voulez pas que plusieurs définitions apparaissent dans votre base de code.

3
wheaties