#c #c #declaration
#c #c #объявление
Вопрос:
Мы можем объявлять функции внутри функций (я хотел локальную переменную, но она анализируется как объявление функции):
struct bvalue;
struct bdict {
bdict(bvalue);
}
struct bvalue {
explict operator bdict() const;
}
struct metainfo {
metainfo(bdict);
}
void foo(bvalue v) {
metainfo mi(bdict(v)); // parses as function declaration
metainfo mi = bdict(v); // workaround
// (this workaround doesn't work in the presence of explicit ctors)
}
Являются ли единственными причинами «потому что это упрощает синтаксический анализатор» и «потому что так говорит стандарт», или для этого есть неясное применение?
Ответ №1:
На самом деле это вопрос C, потому что это поведение было унаследовано непосредственно от C (хотя в C ему уделяется гораздо больше внимания из-за самого неприятного синтаксического анализа).
Я подозреваю, что ответ (по крайней мере, в контексте C) заключается в том, что это позволяет вам ограничить существование ваших объявлений функций именно там, где они необходимы. Возможно, это было полезно в первые дни C. Я сомневаюсь, что кто-нибудь еще это делает, но ради обратной совместимости это нельзя удалить из языка.
Комментарии:
1. В то время глобальное пространство имен было единственным для функций. Как это работает сейчас? Объявление функции, представляющее собой единый идентификатор, относится к пространству имен содержащей его функции или к глобальному? Можете ли вы объявлять функции с пространством имен?
2. Это все еще полезно. Поскольку прототип функции ограничен областью действия функции, в которой он объявлен, можно ссылаться на внешние функции и символы, не фактически загрязняя глобальное пространство имен (с помощью
#include
). Рассмотрим ситуацию, когда требуется вызвать некоторую функцию, объявленную в заголовочном файле, избегая при этом ее включения и позволяя внешнему коду включать ее без конфликтов. Для крайне неубедительных наборов заголовочных файлов (Windows.h
и family, например) это особенно полезно.
Ответ №2:
Это полезно, если вам нужно использовать внешнюю функцию, имя которой будет конфликтовать с внутренней (статической) функцией или переменной в текущей единице перевода (исходном файле). Например (глупо, но это передает суть):
static int read(int x)
{
return bar(x);
}
static int foo()
{
ssize_t read(int, void *, size_t);
read(0, buf, 1);
}
Комментарии:
1. Хм, с gcc все, что я получаю, это ошибка при попытке переопределить read в foo.
2. Ожидается, что вместо этого вы не будете использовать статическую функцию в C , безымянные пространства имен. Плюс, если это ваш предлог использовать созданную ВАМИ функцию с «неправильным именем» вместо переименования вашей функции… это действительно рискованно.
3. @AlexisWilke: Этот вопрос был помечен как C, так и C , и в C это определенно правильный путь. Я согласен, что это была плохая разметка, но я даже не заметил тега C .
Ответ №3:
Объявление функции внутри другой функции скрывает другие перегруженные функции. например, Ошибка компилятора в строке 7
#include <iostream>
void f(int);
int main() {
void f(char *);
f(10); // Line 7
f("Hello world");
return 0;
}
void f(int a) {
std::cout << a;
}
void f(char *str) {
std::cout << str;
}
Комментарии:
1. Значит, вызов
f(10)
перед новым объявлением не выдаст никакой ошибки?
Ответ №4:
Являются ли единственными причинами «потому что это упрощает синтаксический анализатор» и «потому что так говорит стандарт»
Да, в принципе.
Все, что может быть объявлением функции, является объявлением функции.
К сожалению, это один из тех случаев, когда «просто есть».
Комментарии:
1. По-видимому, полезно подделывать пространства имен в C.
2. @Martinho: Но это не поэтому.