По ненаписанным параметрам для функций С++
Ниже приведен совершенно законный код C++
void foo (int) {
cout << "Yo!" << endl;
}
int main (int argc, char const *argv[]) {
foo(5);
return 0;
}
Интересно, имеет ли значение когда-либо оставить неназванные параметры в функциях, учитывая тот факт, что они не могут ссылаться внутри функции.
Зачем это законно начинать?
Ответы
Ответ 1
Да, это законно. Это полезно для реализаций виртуальных машин из базового класса в реализациях, которые не предназначены для использования соответствующего параметра: вы должны объявить параметр, чтобы он соответствовал сигнатуре виртуальной функции в базовом классе, но вы не планируете ее использовать, поэтому вы не укажете имя.
Другим распространенным случаем является предоставление обратного вызова в какой-либо библиотеке, и вы должны соответствовать сигнатуре, которую установила библиотека (спасибо, Aasmund Eldhuset для приведения это вверх).
Существует также специальный случай для определяющий ваши собственные операторы пост-инкремента и пост-декремента: они должны иметь подпись с int
, но этот параметр всегда не используется. Однако это соглашение граничит с взломом в оформлении языка.
Ответ 2
Конечно, неменование параметра является законным при простом объявлении функции, но оно также является законным в реализации. Эта последняя, по-видимому, странная версия полезна, когда функции нужно объявить параметр, чтобы иметь определенную фиксированную подпись, но параметр не нужен.
Это может случиться, например, для метода в производном классе, для функции обратного вызова или для параметра шаблона.
Не указывая параметр, имя указывает, что параметр не нужен, и его значение не будет использоваться. Некоторые компиляторы, если вы вместо этого называете параметр, а затем просто не используете его, выдадут предупреждение о возможной проблеме с телом функции.
Ответ 3
Я просто хочу добавить, что иногда существует разница, называете ли вы параметр или нет. Например, компилятор рассматривает именованное значение rvalue как lvalue и неназванное значение rvalue как rvalue.
// named-reference.cpp
// Compile with: /EHsc
#include <iostream>
using namespace std;
// A class that contains a memory resource.
class MemoryBlock
{
// TODO: Add resources for the class here.
};
void g(const MemoryBlock&)
{
cout << "In g(const MemoryBlock&)." << endl;
}
void g(MemoryBlock&&)
{
cout << "In g(MemoryBlock&&)." << endl;
}
MemoryBlock&& f(MemoryBlock&& block)
{
g(block);
return block;
}
int main()
{
g(f(MemoryBlock()));
}
В этом примере создается следующий вывод:
В g (const MemoryBlock &).
В g (MemoryBlock &).
В этом примере основная функция передает rvalue на f
. Тело f
обрабатывает свой именованный параметр как lvalue. Вызов от f
до g
связывает параметр с ссылкой на lvalue (первая перегруженная версия g
).