является ли f (void) устаревшим в современных C и C ++ [дубликат]
-
03-07-2019 - |
Вопрос
На этот вопрос уже есть ответ здесь:
В настоящее время я занимаюсь рефакторингом / приведением в порядок некоторого старого кода C, используемого в проекте C ++, и регулярно вижу такие функции, как:
int f(void)
который я бы, как правило, написал как:
int f()
Есть ли какая-либо причина не заменять (void) на () по всей кодовой базе, чтобы улучшить согласованность, или есть тонкая разница между ними, о которой я не знаю?Более конкретно, если виртуальная функция-член в C ++ описывается как:
virtual int f(void)
и производный класс включает в себя функцию-член:
int f()
является ли это допустимым переопределением?Кроме того, могу ли я столкнуться с какими-либо проблемами компоновщика, основанными на почти идентичных сигнатурах?
Решение
В C декларация int f(void)
означает функцию, возвращающую значение int, которое не принимает параметров.Декларация int f()
означает функцию, возвращающую значение int, которое принимает любое количество параметров.Таким образом, если у вас есть функция, которая не принимает параметров на C, первая является правильным прототипом.
В C ++, я полагаю int f(void)
является устаревшим, и int f()
является предпочтительным, поскольку это конкретно означает функцию, которая не принимает параметров.
Другие советы
Чтобы добавить к ответу Криса, используя int f()
по моему опыту, это плохая практика в C, поскольку вы теряете способность компилятора сравнивать объявление функции с ее определением, чтобы гарантировать, что она будет вызвана правильно.
Например, следующий код соответствует стандартам C:
#include <stdio.h>
void foo();
void bar(void) {
foo();
}
void foo(int a) {
printf("%d\n", a);
}
Но это приводит к неопределенному поведению, поскольку a
не был передан в foo
.
В C ++ существует две версии foo
:тот, который не принимает аргументов, и тот, который принимает int
.Итак bar
завершается вызовом неопределенной версии, что приведет к ошибке компоновщика (при условии, что нет других определений foo
где угодно).
Приведенные выше ответы вполне верны, но я ссылаюсь на превосходную страницу Дэвида Триббла, поскольку она дает отличное объяснение по этому и многим другим вопросам.
Основные моменты:
C различает функцию , объявленную с пустым списком параметров , и функцию, объявленную с списком параметров, состоящим только из void.Первая является незапрототипированной функцией, принимающей неопределенное количество аргументов, в то время как вторая является прототипированной функцией, не принимающей никаких аргументов.
C ++, с другой стороны, не делает различий между двумя объявлениями и рассматривает их оба как функцию, не принимающую никаких аргументов.
Для кода, который предназначен для компиляции либо как C, либо как C ++, лучшее решение этой проблемы - всегда объявлять функции, не принимающие параметров с явным прототипом void.
Прототипы пустых функций являются устаревшей функцией в C99 (как они были в C89).
Редактировать:Ознакомившись со стандартом, возможно, стоит отметить, что синтаксис func (void) является не устарел в C ++, но обычно считается скорее идиомой в стиле C.Я думаю, что большинство программистов на C ++, с которыми я сталкивался, предпочитают пустой список параметров.
Правка 2:Добавление цитаты из стандарта C ++, раздел 8.3.5, параграф 2:
"Если параметр-declaration-clause пуст, функция не принимает аргументов.Список параметров (void) эквивалентен пустому списку параметров.За исключением этого особого случая, void не должен быть типом параметра (хотя типы, производные от void, такие как void*, могут)."
Там нет упоминания о том, что любая из форм устарела.Еще раз спасибо мистеруОтличный веб-сайт Tribble, который указал мне на правильный раздел стандарта.
tl; dr:использование void
.
Учитывая обратную совместимость в C ++ и некоторую двусмысленность, указанную ниже, я утверждаю, что мы полностью возвращаемся к KnR и ANSI C для получения окончательного ответа:
int getline(void);
int copy(void)
Поскольку специализированные версии getline и copy не имеют аргументов, логика подсказывает, что их прототипы в начале файла должны быть
getline()
иcopy()
.Но для совместимости с более старыми программами на C стандарт принимает пустой список в качестве объявления старого стиля и отключает проверку списка всех аргументов;это словоvoid
должен использоваться для явно пустого списка.[Керниган и Ричи, язык программирования Си, 1988, страницы 32-33]
и..
Особое значение пустого списка аргументов предназначено для того, чтобы разрешить старые программы на C компилироваться с новыми компиляторами.Но это плохая идея использовать его с новыми программами.Если функция принимает аргументы, объявите их;если он не принимает аргументов, используйте void [там же, стр.73]
Редактировать:Остальное вынесите на отдельное обсуждение здесь:Обращается ли указание на использование void в объявлении функции, которая не принимает аргументов, к Самому неприятному синтаксическому анализу?
void f()
является устаревшим, void f(void)
Рекомендуемые:
6.11.6 Описатели функций:
1 Использование деклараторов функций с пустыми круглыми скобками (не параметр формата прототипа деклараторы типов) является устаревшей функцией.
Введение:
2 Некоторые функции устарели, что означает, что их можно рассмотреть на предмет исключения в будущих версиях этого международного стандарта.Они сохранены из-за их широкого использования, но их использование в новых реализациях (для реализации функций) или новых программах (для языка [6.11] или библиотечных функций [7.31]) не рекомендуется.
Подробное обсуждение: https://stackoverflow.com/a/36292431/895245
Проект стандарта C ++ 11 N3337
Ни то , ни другое void f(void)
ни void f()
являются устаревшими.
void f(void)
существует для совместимости с C. Приложение C "Совместимость" C.1.7 Пункт 8:декларанты:
8.3.5 Изменение:В C ++ функция, объявленная с пустым списком параметров, не принимает аргументов.В C пустой список параметров означает, что количество и тип аргументов функции неизвестны.
С тех пор как void f()
устарел в C и void f(void)
Рекомендуемые, void f(void)
будет существовать до тех пор, пока C ++ хочет поддерживать совместимость.
void f(void)
и void f()
то же самое и в C ++.Так что чем дольше void f(void)
имеет смысл только в том случае, если вы заботитесь о написании кода, который компилируется как на C, так и на C ++, что, скорее всего, не стоит того.
Подробное обсуждение: https://stackoverflow.com/a/36835303/895245
В C++, int f(void)
действительно, это устаревшее объявление, которое на 100% эквивалентно int f()
.IT является та же подпись.В void
в этом контексте столь же важно, как, например,пробел.Это также означает, что на них распространяется правило единого определения (они не перегружают) и Derived::f(void)
переопределяет Base::f()
.
Не связывайся с такими вещами, как f(const void)
, хотя.Нет единого мнения о том, что означает такого рода странность.