Почему в коде C ++ отсутствует формальное имя аргумента в определении функции, которое компилируется без предупреждений? - PullRequest
43 голосов
/ 23 февраля 2010

Приступая к работе с некоторым кодом MFC, сгенерированным VS2005, я заметил, что он переопределил метод следующим образом:

void OnDraw(CDC* /*pDC*/)
{
    ...
    // TODO: Add your code here
}

Так что, конечно, как только я добавил что-то, я понял, что мне нужно откомментировать формальный аргумент pDC для компиляции, но я не совсем понимаю, как / почему функция C ++ может компилироваться (без предупреждений) когда формальный аргумент имеет только тип, а не имя:

void foo(int)
{
    int x = 3;
}
int main()
{
    foo(5);
    return 0;
}

Разве это не должно генерировать хотя бы предупреждение (с -Wall или / W4)? Это не похоже на. Я что-то пропустил? Есть ли такой случай, когда это полезно или просто потому, что компилятор не может определить разницу между объявлением функции (требуются только типы) и определением (полностью указанным) до тех пор, пока строка не будет обработана?

Ответы [ 4 ]

52 голосов
/ 23 февраля 2010

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

Относительно того, почему нет никаких предупреждений - я думаю, это потому, что это проблема субъективная, и другие люди (особенно разработчики компиляторов) не видят в этом проблемы. Как только вы действительно перейдете к использованию параметра, вы получите компилятор, который будет жаловаться, если вы забудете раскомментировать имя, чтобы компилятор жаловался только тогда, когда он вам действительно нужен (версия гибкого YAGNI для компилятора: «You Aren» Философия).

Как правило, происходит обратное, когда вы запускаете предупреждения - именованные параметры, которые не используются, генерируют предупреждения - опять же, вероятно, поэтому сгенерированная функция имеет закомментированное имя.

17 голосов
/ 23 февраля 2010

Наиболее распространенная причина, которую я видел, - это подавление предупреждений о неиспользуемых переменных, которые компилятор выдает:

#include <iostream>

void foo(int source)
{
  std::cout << "foo()" << std::endl;
}

int main()
{
  foo(5);
  return 0;
}

gcc говорит: main.cc:3: warning: unused parameter 'source'

Существует два распространенных способа избавиться от предупреждения: закомментировать имя переменной или удалить его полностью:

void foo(int /*source*/)
{
  std::cout << "foo()" << std::endl;
}

против

void foo(int)
{
  std::cout << "foo()" << std::endl;
}

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

Qt (и, возможно, другие платформы) предоставляет макрос, который подавляет предупреждение без необходимости комментировать или удалять имя переменной: Q_UNUSED(<variable>):

void foo(int source)
{
  Q_UNUSED(source); // Removed in version 4.2 due to locusts
  std::cout << "foo()" << std::endl;
}

Это позволяет вам вызвать в теле функции, что переменная не используется, и дает отличное место для документа , почему не используется.

6 голосов

C ++ 11 N3337 стандартная тяга

http://www.open -std.org / jtc1 / sc22 / wg21 / docs /apers / 2012 / n3337.pdf говорит, что это законно в 8.4.1 / 6 «Определения функций> В целом»:

Примечание: неиспользуемые параметры не должны называться. Например,

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

Точнее, 8.4.1 / 1 говорит, что грамматика для определений функций равна

function-definition:
    attribute-specifier-seqopt decl-specifier-seqopt
    declarator virt-specifier-seqopt function-body

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

2 голосов
/ 23 февраля 2010

Он компилируется, потому что в стандарте языка специально сказано, что он должен компилироваться. Там нет другого ответа. Это один из битов, отличающих C ++ от C. В C должны присутствовать имена параметров в определении функции, в C ++ они необязательны.

Мне действительно интересно, почему вы задаете свой вопрос «почему». Видите ли вы что-нибудь неестественное, необычное или нелогичное в этом поведении?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...