Question

    

Cette question a déjà une réponse ici:

         

Je suis actuellement en train de refactoriser / nettoyer un ancien code C utilisé dans un projet C ++ et je vois régulièrement des fonctions telles que:

int f(void)

que j'aurais tendance à écrire comme:

int f()

Y at-il une raison de ne pas remplacer (void) par () dans l’ensemble de la base de code afin d’améliorer la cohérence ou existe-t-il une différence subtile entre les deux que je ne connais pas? Plus précisément, si une fonction membre virtuelle en C ++ est décrite comme suit:

virtual int f(void)

et une classe dérivée inclut une fonction membre:

<*>

est-ce une substitution valide? De plus, suis-je susceptible de rencontrer des problèmes d’éditeur de liens basés sur des signatures presque identiques?

Était-ce utile?

La solution

En C, la déclaration int f (void) désigne une fonction renvoyant int qui ne prend aucun paramètre. La déclaration int f () désigne une fonction renvoyant int qui prend un nombre quelconque de paramètres. Ainsi, si vous avez une fonction qui ne prend aucun paramètre en C, le premier est le bon prototype.

En C ++, je pense que int f (void) est obsolète et que int f () est préféré, car il s'agit spécifiquement d'une fonction qui ne prend aucun paramètre.

Autres conseils

Pour ajouter à la réponse de Chris, utiliser int f () est une mauvaise pratique en C, selon mon expérience, car vous perdez la capacité du compilateur à comparer la déclaration de la fonction à sa définition, pour s'assurer qu'elle sera appelé correctement.

Par exemple, le code suivant est conforme aux normes C:

#include <stdio.h>
void foo();
void bar(void) {
    foo();
}
void foo(int a) {
    printf("%d\n", a);
}

Mais il en résulte un comportement non défini, car un n'a pas été transmis à toto .

En C ++, il existe deux versions de foo : une qui ne prend aucun argument et une qui prend un int . Ainsi, bar appelle la version indéfinie, ce qui entraînerait une erreur de l'éditeur de liens (en supposant qu'il n'y ait pas d'autres définitions de foo nulle part).

Les réponses ci-dessus sont tout à fait correctes, mais je vous renvoie à l'excellente page de David Tribble car elle donne un bonne explication sur ce sujet et sur de nombreux autres.

Les points forts:

  

C distingue une fonction   déclaré avec une liste de paramètres vide   et une fonction déclarée avec un   liste de paramètres composée de   vide. Le premier est un non-prototype   fonction prenant un nombre non spécifié   d'arguments, alors que ce dernier est un   fonction prototypée ne prenant pas   arguments.

     

C ++, en revanche, ne fait pas   distinction entre les deux   déclarations et les considère à la fois   signifier une fonction ne prenant pas   arguments.

     

Pour le code destiné à être   compilé en C ou C ++, le meilleur   la solution à ce problème est de toujours   déclarer des fonctions ne prenant aucun paramètre   avec un prototype de vide explicite.

     

Les prototypes de fonctions vides sont un   fonction obsolète en C99 (car ils   étaient en C89).

Éditer: Après avoir examiné la norme, il convient peut-être de noter que la syntaxe func (void) n'est pas déconseillée en C ++, mais elle est généralement considérée comme un idiome de style C. Je pense que la plupart des programmeurs C ++ que j'ai rencontrés préfèrent la liste de paramètres vide.

Édition 2: Ajout d'une citation de la norme C ++, section 8.3.5, paragraphe 2:

" Si la clause de déclaration de paramètre est vide, la fonction ne prend aucun argument. La liste de paramètres (void) équivaut à la liste de paramètres vide. Sauf dans ce cas particulier, void ne doit pas être un type de paramètre (bien que les types dérivés de void, tels que void *, puissent). "

Rien n’indique que l’un ou l’autre des formulaires est obsolète. Merci encore à l'excellent site Web de M. Tribble pour m'avoir signalé la bonne section de la norme.

tl; dr: utilisez void .

Étant donné la compatibilité ascendante en C ++ et le peu d’ambiguïté identifiée ci-dessous, j’affirme que nous remontons à KnR et à ANSI C pour une réponse concluante:

int getline(void);
int copy(void)
  

Comme les versions spécialisées de getline et copy n'ont pas d'argument,   la logique suggérerait que leurs prototypes au début du fichier   doit être getline () et copy () . Mais pour la compatibilité avec   programmes C plus anciens, la norme prend une liste vide comme à l’ancienne   déclaration et désactive toutes les vérifications de la liste d’arguments; le mot    void doit être utilisé pour une liste explicitement vide.   [Kernighan & amp; Richie, langage de programmation C, 1988, pages 32 à 33]

et ..

  

La signification particulière de la liste des arguments vides est destinée à permettre   programmes C plus anciens à compiler avec de nouveaux compilateurs. Mais c'est une mauvaise idée de   utilisez-le avec de nouveaux programmes. Si la fonction prend des arguments, déclare   leur; si cela ne prend aucun argument, utilisez void [ibid, p. 73]

EDIT: Divisé le reste en une discussion séparée ici: La spécification de l’utilisation de void dans la déclaration d’une fonction ne prenant pas d’argument adresse-t-elle l’analyse la plus frustrante?

Projet de norme C11 N1570

void f () est obsolète, void f (void) recommandé:

6.11.6 Déclarateurs de fonction :

  

1   Utilisation de déclarateurs de fonction avec des parenthèses vides (paramètre non au format prototype   déclarateurs de type) est une fonctionnalité obsolète.

Introduction :

  

2 Certaines fonctionnalités sont obsolètes, ce qui signifie qu'elles peuvent être considérées   retrait lors de futures révisions de la présente Norme internationale. Ils sont retenus car   leur utilisation répandue, mais leur utilisation dans les nouvelles implémentations (pour   fonctions) ou de nouveaux programmes (pour la langue [6.11] ou les fonctions de bibliothèque [7.31]) est déconseillée.

Discussion détaillée: https://stackoverflow.com/a/36292431/895245

C ++ 11 Projet de norme N3337

Ni void f (void) ni void f () ne sont déconseillés.

void f (void) existe pour une compatibilité avec C. Annexe C "Compatibilité" C.1.7 Article 8: déclarateurs :

  

8.3.5 Modification: En C ++, une fonction déclarée avec une liste de paramètres vide ne prend aucun argument. En C, un vide   liste de paramètres signifie que le nombre et le type des arguments de la fonction sont inconnus.

Puisque void f () est obsolète en C et que void f (void) est recommandé, void f (void) existera pour tant que C ++ veut maintenir la compatibilité.

void f (void) et void f () sont identiques en C ++. Ainsi, void f (void) plus long n'a de sens que si vous vous souciez d'écrire du code compilé à la fois en C et en C ++, ce qui n'en vaut probablement pas la peine.

Discussion détaillée: https://stackoverflow.com/a/36835303/895245

En C ++, int f (void) est en effet une déclaration dépréciée équivalente à 100% à int f () . c'est la même signature. Le void dans ce contexte est aussi important que par exemple. les espaces blancs Cela signifie également qu'ils sont soumis à la règle de définition unique (ils ne surchargent pas) et Derived :: f (void) remplace Base :: f () .

Ne jouez pas avec des choses comme f (const void) , cependant. Il n'y a pas beaucoup de consensus sur ce genre de bizarreries.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top