web-dev-qa-db-fra.com

Évitez d'avertir «Paramètre formel non référencé»

J'ai une super classe comme ça:

class Parent
{
public:
    virtual void Function(int param);
};

void Parent::Function(int param)
{
    std::cout << param << std::endl;
}

..et une sous-classe comme celle-ci:

class Child : public Parent
{
public:
    void Function(int param);
};

void Child::Function(int param)
{
    ;//Do nothing
}

Lorsque je compile le fichier .cpp de sous-classe, j'obtiens cette erreur

warning C4100: 'param' : unreferenced formal parameter

En pratique, nous considérions les avertissements comme des erreurs. Comment éviter l'avertissement ci-dessus?

Merci.

46
bdhar

En C++, vous n'avez pas à donner un paramètre que vous n'utilisez pas de nom, vous pouvez donc simplement faire ceci:

void Child::Function(int)
{
    //Do nothing
}

Cependant, vous souhaiterez peut-être conserver le nom du paramètre dans la déclaration dans le fichier d'en-tête à des fins de documentation. L'instruction vide (;) est également inutile.

85
CB Bailey

Je préfère utiliser une macro, car elle indique non seulement au compilateur mon intention, mais aussi aux autres responsables du code, et elle sera consultable plus tard.

La méthode de commenter le nom de l'argument peut facilement être manquée par des personnes qui ne connaissent pas le code (ou moi 6 mois plus tard).

Cependant, c'est un problème de style, aucune des méthodes n'est "meilleure" ou plus optimale en ce qui concerne le code généré, les performances ou la robustesse. Pour moi, le facteur décisif est d'informer les autres de mon intention grâce à un système standardisé. Omettre le nom du paramètre et ajouter un commentaire fonctionnerait tout aussi bien:

void CFooBar::OnLvnItemchanged(NMHDR *pNMHDR, LRESULT *pResult)
{
    UNREFERENCED_PARAMETER(pNMHDR);

Alternativement:

void CFooBar::OnLvnItemchanged(NMHDR* /* pNMHDR */, LRESULT *pResult)
{
    // Not using: pNMHDR

Je dirais que la pire solution est de supprimer le message d'avertissement; que cela affectera l'ensemble de votre fichier ou projet, et vous perdrez la connaissance que vous avez peut-être oublié quelque chose. Au moins en ajoutant la macro ou en commentant le nom de l'argument, vous avez dit aux autres que vous avez pris la décision consciente de ne pas utiliser cet argument et que ce n'est pas une erreur.

Le SDK Windows dans WinNT.h définit UNREFERENCED_PARAMETER() avec DBG_UNREFERENCED_PARAMETER() et DBG_UNREFERENCED_LOCAL_VARIABLE(). Ils évaluent tous la même chose, mais la différence est que DBG_UNREFERENCED_PARAMETER () est utilisé lorsque vous démarrez et comptez utiliser le paramètre lorsque le code est plus complet. Lorsque vous êtes sûr de ne jamais utiliser le paramètre, utilisez la version UNREFERENCED_PARAMETER ().

Les classes Microsoft Foundation Classes (MFC) ont une convention similaire, avec les macros UNUSED() et UNUSED_ALWAYS() plus courtes.

Choisissez un style et respectez-le. De cette façon, plus tard, vous pouvez rechercher "DBG_UNREFERENCED_PARAMETER" Dans votre code et trouver toutes les instances où vous vous attendiez à utiliser un argument, mais vous ne l'avez pas fait. En adoptant un style cohérent et en l'utilisant habituellement, vous le rendrez plus facile pour les autres et vous-même plus tard.

28
Charles Oppermann

Une autre technique que vous pouvez utiliser si vous souhaitez conserver le nom du paramètre est de transtyper pour annuler:

void Child::Function(int param)
{
    (void)param;   //Do nothing
}
19
R Samuel Klatchko

Comme @Charles Bailey l'a mentionné, vous pouvez ignorer le nom du paramètre.

Cependant, dans certains scénarios, vous avez besoin du nom du paramètre, car dans les versions de débogage, vous appelez une ASSERT(), mais sur les versions de vente au détail, c'est un nop. Pour ces scénarios, il y a des macros pratiques (au moins dans VC++ :-)) UNREFERENCED_PARAMETER(), qui est définie comme ceci:

#define UNREFERENCED_PARAMETER(x) x

Notez que la distribution simple @R Samuel Klatchko publiée fonctionne également, mais je la trouve personnellement plus lisible si le code est explicite qu'il s'agit d'un paramètre non référencé par rapport à une distribution simple inexpliquée comme celle-ci.

8
Franci Penov

Pragma fonctionne aussi très bien car il est clair que vous utilisez VS. Cet avertissement présente un rapport bruit/avantage très élevé, étant donné que les paramètres non référencés sont très courants dans les interfaces de rappel et les méthodes dérivées. Même les équipes de Microsoft Windows qui utilisent W4 se sont lassées de son inutilité (seraient plus adaptées à/Wall) et ont simplement ajouté à leur projet:

#pragma warning(disable: 4100)

Si vous souhaitez atténuer l'avertissement d'un simple bloc de code, entourez-le de:

#pragma warning(Push)
#pragma warning(disable: 4100)
void SomeCallbackOrOverride(int x, float y) { }
#pragma warning(pop)

La pratique de laisser de côté le nom du paramètre a l'inconvénient dans le débogueur que vous ne pouvez pas facilement inspecter par son nom ni l'ajouter à la montre (devient confus si vous avez plus d'un paramètre non référencé), et alors qu'une implémentation particulière d'une méthode peut ne pas utiliser le paramètre, connaître sa valeur peut vous aider à déterminer à quelle étape d'un processus vous vous trouvez, en particulier lorsque vous n'avez pas toute la pile d'appels au-dessus de vous.

5
Dwayne Robinson

J'utiliserais une macro pour supprimer l'avertissement de paramètre formel non référencé:

#define UNUSED( x ) ( &reinterpret_cast< const int& >( x ) )

Cela présente les avantages suivants:

  • Contrairement à #define UNUSED (x) (void) x, il n'introduit pas la nécessité de voir la définition complète du type du paramètre là où aucun besoin de ce type n'existait auparavant.
  • Contrairement à #define UNUSED (x) & x, il peut être utilisé en toute sécurité avec des paramètres dont les types surchargent l'opérateur unaire &.
4
TheBeardyMan