NB Il ne s'agit pas de savoir comment utiliser les fonctions en ligne ou comment elles fonctionnent, mais plutôt pourquoi elles sont faites telles qu'elles sont.
La déclaration d'une fonction membre de classe n'a pas besoin de définir une fonction car inline
il s'agit uniquement de l'implémentation réelle de la fonction. Par exemple, dans le fichier d'en-tête:
struct foo{
void bar(); // no need to define this as inline
}
Alors pourquoi l'implémentation en ligne d'une fonction de classes doit-elle se trouver dans le fichier d'en-tête? Pourquoi ne puis-je pas mettre la fonction en ligne dans le .cpp
fichier? Si je devais essayer de mettre la définition en ligne dans le .cpp
fichier, j'obtiendrais une erreur du type:
error LNK2019: unresolved external symbol
"public: void __thiscall foo::bar(void)"
(?bar@foo@@QAEXXZ) referenced in function _main
1>C:\Users\Me\Documents\Visual Studio 2012\Projects\inline\Debug\inline.exe
: fatal error LNK1120: 1 unresolved externals
inline
apparaît sur une définition mais pas sur une déclaration préalable vs vice versa . Si tel est le cas, cela peut aider: stackoverflow.com/questions/4924912/…Réponses:
La définition d'une
inline
fonction n'a pas besoin d'être dans un fichier d'en-tête mais, en raison de la règle de définition unique ( ODR ) pour les fonctions en ligne, une définition identique pour la fonction doit exister dans chaque unité de traduction qui l'utilise.Le moyen le plus simple d'y parvenir est de placer la définition dans un fichier d'en-tête.
Si vous souhaitez mettre la définition d'une fonction dans un seul fichier source, vous ne devez pas la déclarer
inline
. Une fonction non déclaréeinline
ne signifie pas que le compilateur ne peut pas intégrer la fonction.Que vous deviez déclarer une fonction
inline
ou non est généralement un choix que vous devez faire en fonction de la version des règles de définition unique qu'il est le plus logique pour vous de suivre; ajouterinline
puis être restreint par les contraintes ultérieures n'a pas de sens.la source
+1
de ma part!Il y a deux façons de l'examiner:
Les fonctions en ligne sont définies dans l'en-tête car, pour insérer un appel de fonction, le compilateur doit pouvoir voir le corps de la fonction. Pour qu'un compilateur naïf fasse cela, le corps de la fonction doit être dans la même unité de traduction que l'appel. (Un compilateur moderne peut optimiser toutes les unités de traduction, et donc un appel de fonction peut être incorporé même si la définition de fonction est dans une unité de traduction séparée, mais ces optimisations sont coûteuses, ne sont pas toujours activées et n'ont pas toujours été prises en charge par le compilateur)
les fonctions définies dans l'en-tête doivent être marquées
inline
car sinon, chaque unité de traduction qui comprend l'en-tête contiendra une définition de la fonction, et l'éditeur de liens se plaindra de plusieurs définitions (une violation de la règle d'une définition). Leinline
mot-clé supprime cela, permettant à plusieurs unités de traduction de contenir des définitions (identiques).Les deux explications se résument vraiment au fait que le
inline
mot-clé ne fait pas exactement ce que vous attendez.Un compilateur C ++ est libre d'appliquer l' optimisation en ligne (remplacer un appel de fonction par le corps de la fonction appelée, en économisant la surcharge d'appel) à tout moment, tant que cela ne modifie pas le comportement observable du programme.
Le
inline
mot-clé facilite l'application de cette optimisation par le compilateur, en permettant à la définition de la fonction d'être visible dans plusieurs unités de traduction, mais l'utilisation du mot-clé ne signifie pas que le compilateur doit intégrer la fonction, et ne pas utiliser le mot-clé interdire au compilateur d'insérer la fonction.la source
Il s'agit d'une limite du compilateur C ++. Si vous mettez la fonction dans l'en-tête, tous les fichiers cpp où elle peut être insérée peuvent voir la "source" de votre fonction et l'inlining peut être fait par le compilateur. Sinon, l'inlining devrait être fait par l'éditeur de liens (chaque fichier cpp est compilé dans un fichier obj séparément). Le problème est qu'il serait beaucoup plus difficile de le faire dans l'éditeur de liens. Un problème similaire existe avec les classes / fonctions "modèles". Ils doivent être instanciés par le compilateur, car l'éditeur de liens aurait des problèmes pour les instancier (en créant une version spécialisée). Certains compilateurs / éditeurs de liens plus récents peuvent faire une compilation / liaison en "deux passes" où le compilateur fait une première passe, puis l'éditeur de liens fait son travail et appelle le compilateur pour résoudre les choses non résolues (inline / templates ...)
la source
La raison est que le compilateur doit réellement voir la définition afin de pouvoir la déposer à la place de l'appel.
Rappelez-vous que C et C ++ utilisent un modèle de compilation très simpliste, où le compilateur ne voit toujours qu'une seule unité de traduction à la fois. (Cela échoue pour l'exportation, ce qui est la principale raison pour laquelle un seul fournisseur l'a mis en œuvre.)
la source
Le
inline
mot-clé c ++ est trompeur, il ne signifie pas "en ligne cette fonction". Si une fonction est définie comme inline, cela signifie simplement qu'elle peut être définie plusieurs fois tant que toutes les définitions sont égales. Il est parfaitement légal pour une fonction marquéeinline
d'être une fonction réelle qui est appelée au lieu d'obtenir du code incorporé au point où elle est appelée.La définition d'une fonction dans un fichier d'en-tête est nécessaire pour les modèles, car par exemple, une classe basée sur un modèle n'est pas vraiment une classe, c'est un modèle pour une classe dont vous pouvez faire plusieurs variantes. Pour que le compilateur puisse par exemple créer une
Foo<int>::bar()
fonction lorsque vous utilisez le modèle Foo pour créer une classe Foo , la définition réelle deFoo<T>::bar()
doit être visible.la source
inline
(et ne la déclarez pas non plus qu'elleinline
ne sera pas insérée).Je sais que c'est un vieux fil mais j'ai pensé que je devrais mentionner que le
extern
mot - clé. J'ai récemment rencontré ce problème et résolu comme suitHelper.h
Helper.cpp
la source
Parce que le compilateur a besoin de les voir pour les incorporer . Et les fichiers d'en-tête sont les «composants» qui sont généralement inclus dans d'autres unités de traduction.
la source
Fonctions en ligne
En C ++, une macro n'est rien d'autre qu'une fonction en ligne. Donc maintenant les macros sont sous le contrôle du compilateur.
Le code de la fonction Inline est remplacé à l'endroit où il est appelé, ce qui réduit la surcharge de la fonction d'appel.
Dans certains cas, l'intégration de la fonction ne peut pas fonctionner, comme
Si une variable statique est utilisée dans une fonction en ligne.
Si la fonction est compliquée.
Si appel récursif de fonction
Si l'adresse de la fonction prise implicitement ou explicitement
La fonction définie en dehors de la classe comme ci-dessous peut devenir en ligne
La fonction définie à l'intérieur de la classe devient également en ligne
Ici, les fonctions getSpeed et setSpeed deviendront en ligne
la source