2016-11-04 5 views
5

Existe-t-il un moyen d'être averti de l'absence d'appariement des noms d'arguments entre une déclaration de fonction et sa définition?C++ Comment avertir de la différence entre les noms d'arguments dans la déclaration de fonction et la définition

Déclaration

double divide(int a, int b); 

Définition

double divide(int b, int a) 
{ 
    return a/b; 
} 

Pour un utilisateur, qui utilisent la fonction divide s'attendront a/b en conséquence et non b/a.

Je sais, le compilateur ne peut pas faire cela, mais y a-t-il des outils d'analyse statique qui peuvent le faire? Si oui, lesquels?

+0

arguments sont positionnels seulement en C. J'ai testé avec «-Wall» et pas de chance BTW. –

+0

Pour la simple raison que si quelqu'un ne sait pas comment la fonction est déclarée, elle pourrait en obtenir des résultats inattendus. Par exemple a/b! = B/a – lucab0ni

+1

bien sûr, c'est un vrai problème. Mais en C cela ne peut pas être fait. Je suis sûr que certains analyseurs de code comme ClokWork ou Logiscope proposent de telles vérifications. –

Répondre

0

Le compilateur ne se soucie pas des noms d'argument dans votre déclinaison, vous pouvez même écrire void foo(int, int);, donc il n'y a pas de discordance, et il n'y a pas d'avertissement. Si, pour une raison ou une autre, vous trouvez que cette incompatibilité est confuse, omettez simplement les noms d'arguments dans les déclarations.

+1

"juste omettre les noms d'arguments dans les déclarations.", Je pense que la raison pour laquelle il veut l'avertissement est que la fonction est claire juste en regardant la déclaration. – George

+0

@George, peut-être. Mais qu'est-ce qui est "clair" à propos des variables appelées "a" et "b"?Je vois une 'division 'de deux entiers appelés' a' et 'b'. –

+1

@AaronMcDaid: Je pense qu'un exemple plus réaliste serait 'void copy (int * src, int * dest)' échanger les noms serait * mauvais *. (Oui, je me rends compte que 'src' devrait être' const int * '). –

0

Êtes-vous simplement intéressé par la vérification du code existant, ou voulez-vous vous assurer que le code évite ce problème et que vous êtes prêt à reconcevoir les interfaces?

Dans ce dernier cas:

Si vous avez plusieurs arguments du même type alors des incohérences peuvent être un problème (et je l'ai vu pire que votre exemple):

void foo(bool fast, bool small, bool trivial); 
foo(true, false, false); 

Ce que vous demandez car est un moyen de s'assurer que la déclaration et la définition de foo sont cohérentes - mais vous ignorez les incohérences entre l'appel et la déclaration.

Une solution différente consiste à créer à la place un argument-struct avec setRoutines. Quelque chose comme:

struct FooArg { 
    bool fast, small, trivial; 
    FooArg &setFast(bool fast_) {fast=fast_;return *this;}; 
    ... 
}; 
void foo(FooArg const&); 
foo(FooArg().setFast(true).setSmall(false)...); 

Vous pouvez alors éviter la contradiction entre la déclaration, la définition et appeler, mais doivent être plus bavard. (Je suis sûr qu'il ya une réponse à propos de cette technique quelque part.)

+0

Cela ne vous intéresse que de vérifier le code. Dans mon cas, la déclaration est générée par un outil, la définition est manuelle. – lucab0ni

+0

Et je suppose que le fait que l'outil génère des définitions de stub vaudra trop de travail, surtout si l'outil doit être réexécuté pour générer de nouvelles déclarations, tout en conservant certaines des définitions existantes. –

+0

oui, c'est le point – lucab0ni