2010-09-05 3 views
1

j'ai ces fichiers:fonction inline récursive

//Q2a.h 
#ifndef Q2A_H 
#define Q2A_H 

inline int MyFactorial(int a) 
{ 
if (a < 2) 
    return 1; 
return a*MyFactorial(a-1); 
} 

int NumPermutations(int b); 
#endif 

//Q2a.cpp 
#include "Q2a.h" 

int NumPermutations(int b) 
{ 
    return MyFactorial(b); 
} 

and file with the main- Q2b.cpp 

Je remarque que le compilateur ignore généralement le decleration en ligne quand il y a des fonctions récursives. mais ma question est pourquoi si je retire la déclaration en ligne, je peux faire:

g++ -Wall -g -c Q2a.cpp -o Q2a.o 
g++ -Wall -g -c Q2b.cpp -o Q2b.o 

ceux qui sont très bien, mais à l'étape de liaison:

g++ -Wall -g -c Q2a.o Q2b.o -o Q2 

j'obtiens une erreur: définition multiple de ` MyFactorial (int)

Répondre

1

Parce que lorsque vous #include "Q2a.h", vous effectuez essentiellement une substitution de texte du contenu, à la fois Q2a.cpp et Q2b.cpp finissent par définir une fonction appelée MyFactorial(). Vous devez utiliser inline ou définir la fonction dans l'un des fichiers source.

Notez que l'utilisation de inline n'aidera pas beaucoup avec une fonction récursive!

+0

La queue-récursive 'inline' est raisonnable, mais ce n'est pas le cas. – Potatoswatter

1

Avec GCC déclarant une fonction comme inline indiquera juste le compilateur pour inline la fonction. Cependant, le compilateur génère toujours une fonction non-inline que vous pouvez appeler depuis une unité de compilation différente.

Ces fonctions avaient une collision de nom dans votre cas. Dit simplement: inline n'implique pas statique.

Qu'est-ce que vous voulez faire est de déclarer les fonctions static inline

Cela indiquera la compilation que vous voulez que votre ligne de fonction, et - si le compilateur décide de ce inline - pas de version statique de la même fonction est Champs obligatoires. Si le compilateur ne peut pas aligner la fonction, il s'assurera que la fonction est statique, par ex. le nom de la fonction est local dans le fichier C et aucune collision de nom ne se produit pendant la liaison du programme.

Conseil:

Compilateurs ont un comportement différent. Si vous voulez compiler le code sur une plate-forme différente à l'avenir, assurez-vous de cacher la définition dans une macro.

Par exemple, je dois utiliser static inline pour le GCC et Visual Studio et un _inline simple pour le code TI Composer DSP/compilateur ARM intégré. Le compilateur plus tard ne comprend pas un en ligne normal parce qu'il est non standard et ne comprendra pas le _inline statique non plus.

+0

De la norme: "7.1.1 Spécificateurs de classes de stockage - Les spécificateurs de classe de stockage sont spécificateur de classe de stockage: 'auto register static extern mutable' ** Au plus un spécificateur de classe de stockage doit apparaître dans un décl-specifier-seq donné." * * – Potatoswatter

+0

'inline' est comme statique, mais supérieur si les définitions de fonctions sont identiques.' Static' dit "ceci sera défini dans plusieurs fichiers, peut-être différemment. 'inline' dit" ceci sera défini dans plusieurs fichiers, de manière interchangeable. " L'indice de génération de code est un effet secondaire. – Potatoswatter

1

Lorsque vous déclarez une fonction inline, vous modifiez les règles qui s'appliquent aux définitions de votre fonction.

Une fonction non inline ne doit être définie qu'une seule fois dans un programme; en revanche, une fonction inline peut être définie dans plusieurs unités de traduction, bien que les définitions doivent être identiques et la fonction doit être définie dans chaque traduction dans laquelle elle est utilisée. En supprimant inline, vous supprimez l'exemption de la "règle de définition unique" que vous aviez précédemment.