43 votes

Pourquoi une fonction sans identifiant d'argument est-elle valide en C++ ?

Étant donné une fonction en C++ avec des arguments qui ne sont que des types et n'ont pas d'identifiants,

 void foo1(int, int, int){cout << "called foo1";}

Je peux l'appeler comme ça :

int main()
{
    foo1(10, 10, 10);
}

Pourquoi est-ce une construction valide en C++ ? S'agit-il simplement d'une idiosyncrasie du C++, ou ce type de déclaration a-t-il réellement une utilité ? Peut-on réellement accéder aux arguments qui ont été passés d'une manière ou d'une autre ? (Ce type de déclaration de méthode ne fonctionnera pas en Java).

17 votes

Réduire au silence les avertissements concernant les paramètres inutilisés.

0 votes

Je n'ai reçu aucun avertissement dans Visual Studio en utilisant les paramètres par défaut pour le code ci-dessus.

9 votes

Parfois, vous avez simplement besoin d'une signature spécifique pour vous conformer à une interface donnée. Mais vous n'avez pas vraiment besoin du paramètre.

46voto

user4581301 Points 18060

Considérons un cas où l'on vous demande de fournir une fonction qui répond au prototype suivant

void dostuff(int x, int y, int z);

Et disons que vous opérez dans un espace 2D et que vous n'utilisez pas de z dans votre implémentation. Vous pouvez

void dostuff(int x, int y, int z)
{
    // use x and y
}

et d'ignorer z mais le compilateur repérera probablement que vous avez défini mais pas utilisé z et vous avertir que vous pourriez faire une erreur. Au lieu de cela, vous pouvez

void dostuff(int x, int y, int )
{
    // use x and y
}

et laisser de côté la définition de z . Le compilateur accepte et rejette silencieusement le troisième paramètre car il sait que vous ne le voulez pas.

Vous ne voulez pas simplement désactiver l'avertissement à cause d'erreurs comme celle-ci

void dostuff(int x, int y, int z)
{
    for (int z = 0; z < MAX; z++)
    {
        // use x and y and z, the local z. 
    }
}

Lorsqu'un index de boucle mal nommé fait de l'ombre au paramètre z . L'entrée de l'appelant est maintenant ignorée et cela pourrait avoir de mauvaises conséquences. Cette erreur est souvent difficile à repérer avec l'œil de la marque 1, surtout si l'entrée locale z est enfouie quelque part dans une fonction complexe.

Chaque fois que le compilateur peut repérer un bogue possible dans votre code, profitez-en. Cela signifie moins de travail pour vous.

8 votes

Personnellement, j'aime matérialiser l'argument non utilisé par des commentaires : int /*z*/ . Cela permet de rappeler ce qu'est l'argument et à quoi il peut servir.

2 votes

Pour votre exemple de shadowing, je pense que le compilateur devrait (aussi) avertir sur le shadowing lui-même ; je ne vois pas beaucoup de situations où nous aurions intentionnellement shadowé un paramètre ou une variable locale avec une autre variable locale, même si le shadowee est toujours utilisé quelque part en dehors de la portée du shadower.

17voto

user2328447 Points 1274

Une déclaration comme

void foo1(int, int, int){cout << "called foo1";}

montre clairement dans la déclaration, que vous voulez remplir une exigence avec votre fonction - par exemple, surcharger une fonction spécifique dans la classe ou l'interface de base, qui pourrait par exemple y être déclarée en tant que

virtual void foo1(int something, int another, int andAnother) = 0;

MAIS vous n'avez pas l'intention d'utiliser les paramètres qui vous sont remis.

Un autre exemple serait de vouloir transférer la fonction vers, par exemple, une autre fonction qui attend un pointeur de fonction vers une fonction void avec trois paramètres int.

void giveMeFoo( void (*fn)(int, int, int) ) { ... }

En outre, les niveaux d'avertissement supérieurs émettent un avertissement si des paramètres sont déclarés, qui ne sont pas évalués dans le corps de la fonction. Vous pouvez éviter cela en laissant de côté les noms des paramètres.

Les paramètres sans nom ne sont alors plus accessibles dans le corps de la fonction - volontairement. L'utilisateur 4581301 a joliment décrit pourquoi.

Déclarer une fonction autonome sans nom de paramètre comme dans votre exemple est autorisé en raison des utilisations décrites ci-dessus, mais cela n'a évidemment aucun sens dans la plupart des cas. Un exemple où cela a un sens est dans la section des commentaires. Un autre exemple de fonction autonome sans nom de paramètre pourrait être le suivant : vous écrivez une bibliothèque et vous souhaitez maintenir une compatibilité ascendante (la fonction de votre bibliothèque n'a plus besoin du paramètre, mais vous ne voulez pas rompre la déclaration de l'en-tête public) ou vous voulez réserver un paramètre pour une utilisation future.

4 votes

Les fonctions libres avec des arguments non nommés ne sont pas une absurdité, c'est juste peu commun. Voir un exemple standard .

0 votes

OK thx... un paramètre fictif est une utilisation qui n'a pas de sens... mais plutôt rare :D

11voto

Rxmsc Points 927

Oui . Il est légal en C++.

Norme C++11 n3337 8.4.1(p6) Définitions de fonctions :

Remarque : les paramètres inutilisés ne doivent pas nécessairement être nommés. Par exemple,

void print(int a, int) {
    std::printf("a = %d\n", a);
}

Norme C++14 :

[ 8.3.5.11] Un identificateur peut éventuellement être fourni comme nom de paramètre ; s'il est présent dans une définition de fonction, il nomme un paramètre (parfois appelé "argument formel"). [Note : En particulier, les noms de paramètres sont également facultatifs dans les définitions de fonctions et les noms utilisés pour un paramètre dans différentes déclarations et dans la définition d'une fonction. paramètre dans des déclarations différentes et dans la définition d'une fonction ne doivent pas nécessairement être les mêmes].

8 votes

Cela ne répond pas à la question.

7 votes

@juanchopanza Strictement parlant, c'est le cas. Pourquoi est-elle valide ? Parce que la norme le dit explicitement. Elle n'entre pas dans tous les détails, bien sûr.

2 votes

Je ne pense pas que "Pourquoi c'est valable ?" "Parce que ça l'est" répond à la question. Edit : en fait, je pense que cela répond à la question "Pouvons-nous réellement accéder aux arguments qui ont été passés d'une manière ou d'une autre ?".

7voto

Carlos Points 1652

C'est légal, et si vous vous demandez pourquoi :

Typiquement, les arguments non nommés proviennent de la simplification du code ou de la planification d'extensions. Dans les deux cas, laisser l'argument l'argument en place, bien que non utilisé, assure que les appelants ne sont pas ne sont pas affectés par le changement.

Extrait de : Bjarne Stroustrup. "Le langage de programmation C++, quatrième édition".

0voto

L'idée est que vous pourriez vouloir modifier la définition de la fonction pour utiliser le caractère de remplacement plus tard, sans modifier tout le code code où la fonction est appelée.

Les arguments dans une déclaration de fonction peuvent être déclarés sans identificateurs. Lorsque ceux-ci sont utilisés avec des arguments par défaut, cela peut paraître un peu bizarre. Vous pouvez vous retrouver avec :

void f(int x, int = 0, float = 1.1);

En C++, vous n'avez pas non plus besoin d'identificateurs dans la définition de la fonction :

void f(int x, int, float flt) { /* ... */ }

Dans le corps de fonction, x et flt peuvent être référencés, mais pas le l'argument du milieu, car il n'a pas de nom. Les appels de fonction doivent toujours fournir une valeur pour le placeholder : f(1) o f(1,2,3.0) . Cette syntaxe syntaxe vous permet d'insérer l'argument en tant qu'espace sans l'utiliser. l'utiliser.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X