Избегайте предупреждения «Формальный параметр без ссылки» - PullRequest
45 голосов
/ 11 июня 2010

У меня супер класс такой:

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

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

.. и такой подкласс:

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

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

Когда я компилирую файл .cpp подкласса, я получаю эту ошибку

warning C4100: 'param' : unreferenced formal parameter

На практике мы привыкли рассматривать предупреждения как ошибки. Как избежать вышеуказанного предупреждения?

Спасибо.

Ответы [ 6 ]

83 голосов
/ 11 июня 2010

В C ++ вам не нужно указывать параметр, для которого вы не используете имя, поэтому вы можете просто сделать это:

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

Возможно, вы захотите сохранить имя параметра в объявлении взаголовочный файл в порядке документации, хотя.Пустой оператор (;) также не нужен.

28 голосов
/ 25 июля 2011

Я предпочитаю использовать макрос, так как он сообщает не только компилятору о моих намерениях, но и другим сопровождающим кода, и он доступен для поиска позже.

Метод комментирования имени аргумента может быть легко пропущен людьми, незнакомыми с кодом (или мной 6 месяцев спустя).

Однако это проблема стиля, ни один из методов не является «лучшим» или более оптимальным с точки зрения генерируемого кода, производительности или надежности. Для меня решающим фактором является информирование других о моем намерении через стандартизированную систему. Пропуск имени параметра и добавление комментария будет работать одинаково хорошо:

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

В качестве альтернативы:

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

Я бы сказал, что худшим решением является подавление предупреждающего сообщения; это повлияет на весь ваш файл или проект, и вы потеряете знание о том, что, возможно, вы что-то упустили. По крайней мере, добавив макрос или закомментировав имя аргумента, вы сказали другим, что приняли сознательное решение не использовать этот аргумент и что это не ошибка.

Windows SDK в WinNT.h определяет UNREFERENCED_PARAMETER() вместе с DBG_UNREFERENCED_PARAMETER() и DBG_UNREFERENCED_LOCAL_VARIABLE(). Все они оценивают одно и то же, но разница в том, что DBG_UNREFERENCED_PARAMETER () используется, когда вы начинаете, и ожидаете использовать параметр, когда код будет более полным. Если вы уверены, что никогда не будете использовать этот параметр, используйте версию UNREFERENCED_PARAMETER ().

У базовых классов Microsoft (MFC) есть аналогичное соглашение с более короткими макросами UNUSED() и UNUSED_ALWAYS().

Выберите стиль и придерживайтесь его. Таким образом, позже вы можете искать «DBG_UNREFERENCED_PARAMETER» в своем коде и находить любые случаи, когда вы ожидали использовать аргумент, но не сделали этого. Приняв непротиворечивый стиль и привычно используя его, вы потом упростите его для других и для себя.

19 голосов
/ 11 июня 2010

Другой метод, который вы можете использовать, если хотите сохранить имя параметра, - привести к void:

void Child::Function(int param)
{
    (void)param;   //Do nothing
}
8 голосов
/ 11 июня 2010

Как упомянул @Charles Bailey, вы можете пропустить имя параметра.

Однако в некоторых случаях вам нужно имя параметра, так как в отладочных сборках вы вызываете ASSERT() для него, но дляРитейл строит это nop.Для этих сценариев есть удобные макросы (по крайней мере, в VC ++ :-)) UNREFERENCED_PARAMETER(), которые определены следующим образом:

#define UNREFERENCED_PARAMETER(x) x

Обратите внимание, что простой приведенный @R Сэмюэль Клатчко, опубликованный также, работает, но ялично я нахожу это более читабельным, если в коде явно указано, что это параметр без ссылки, а не просто необъяснимое приведение типа.

4 голосов
/ 28 октября 2014

Прагма тоже хорошо работает, так как ясно, что вы используете VS.Это предупреждение имеет очень высокое отношение шума к выгоде, учитывая, что параметры без ссылок очень распространены в интерфейсах обратного вызова и производных методах.Даже команды в Microsoft Windows, которые используют W4, устали от его бессмысленности (было бы более подходящим для / Wall) и просто добавили в свой проект:

#pragma warning(disable: 4100)

Если вы хотите снять предупреждение только для блокакода, окружите его:

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

Практика исключения имени параметра имеет недостаток в отладчике, который вы не можете легко проверить по имени или добавить в часы (если выиметь более одного параметра, на который нет ссылок), и хотя конкретная реализация метода может не использовать этот параметр, знание его значения может помочь вам выяснить, на какой стадии процесса вы находитесь, особенно если у вас нет всего стека вызовов вышевы.

4 голосов
/ 19 января 2012

Я бы использовал макрос для подавления необязательного предупреждения о формальном параметре:

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

Это имеет следующие преимущества:

  • В отличие от #define UNUSED (x) (void)x, он не вводит необходимость полного определения типа параметра, который можно увидеть там, где такой необходимости раньше не было.
  • В отличие от #define UNUSED (x) & x, его можно безопасно использовать спараметры, типы которых перегружают унарный оператор &.
...