прямое объявление функции внутри другой функции

Код идет первым:

void foo(int x)
{
    void bar(int);  //is this forward-decl legal?
    bar(x);
}

void bar(int x)
{
    //do stuff
}

В приведенном выше коде foo вызывает bar, обычно я помещаю forward-decl bar вне foo, например так:

void bar(int);
void foo(int x) 
{
    bar();
}

Во-первых, я думаю, что можно поместить forward-decl bar внутрь foo, верно?

Во-вторых, рассмотрите это, если bar является функцией static следующим образом:

static void bar(int x)
{
    //do stuff
}

Тогда как я должен объявить об этом вперед? Я имею в виду, должен ли forward-decl принимать или опускать static?


person Alcott    schedule 08.02.2012    source источник
comment
Если это C++, то у вас не должен быть тег c в вашем вопросе, и следует использовать безымянное пространство имен, а не ключевое слово static. Если это C, то у вас не должен быть тег c++ в вашем вопросе, и следует помечать ваши предварительные объявления как static.   -  person ruakh    schedule 08.02.2012
comment
@ruakh: использование static не устарело, хотя некоторые упорно утверждают, что это так. static и безымянные пространства имен имеют свои преимущества.   -  person Ben Voigt    schedule 08.02.2012
comment
@BenVoigt, преимущества? Такие как?   -  person Alcott    schedule 08.02.2012
comment
@Alcott: не раздувать таблицу внешних имен, что означает меньше работы для компоновщика. Большим преимуществом безымянного пространства имен в C++03 было то, что оно было совместимо с параметрами шаблона, но в C++11 они больше не требуют внешней связи.   -  person Ben Voigt    schedule 08.02.2012
comment
@BenVoigt: Спасибо за эту информацию. (Для всех, кто читает это, кто, как и я, сталкивался с этим постоянным утверждением и удивлен комментарием Бена Фойгта: как оказалось, в некоторых рабочих черновиках C++11 говорилось, что static устарело при объявлении объектов в пространство имен, но этот оператор был позже удален.)   -  person ruakh    schedule 08.02.2012


Ответы (2)


  1. Да, допустимо размещать предварительную декларацию внутри другой функции. Тогда его можно использовать только в этой функции. И пространство имен функции, в которую вы его поместите, будет использоваться, поэтому убедитесь, что оно совпадает.

  2. Стандарт гласит: «Связи, подразумеваемые последовательными объявлениями для данного объекта, должны согласовываться». (раздел 7.1.2). Так что да, прототип тоже должен быть static. Однако не похоже, что размещение прототипа функции связи static внутри другой функции вообще разрешено. «В блоке не может быть объявлений функций static» (тот же раздел).

person Ben Voigt    schedule 08.02.2012
comment
Проще говоря, я не могу предварительно объявить bar внутри foo, если bar равно static, верно? - person Alcott; 08.02.2012
comment
@Alcott: Согласно моему прочтению Стандарта, это правильно. Я бы протестировал с Comeau try-it-out, у них почти идеальное соответствие стандарту (ну, C++03, и они работают над C++11). - person Ben Voigt; 08.02.2012

Да, можно поместить предварительное объявление внутри функции. Неважно, где он находится, если компилятор увидел его до того, как вы вызовете функцию. Вы также можете предварительно объявлять функции в пространствах имен. Однако прототипы ограничены рамками, в которых они находятся:

int blah() {
    { void foo(); }

    foo(); // error: foo not declared
}

Во-вторых, вам нужно всего лишь поместить static в прототип, иначе компилятор будет жаловаться на то, что bar объявлен extern (все прототипы неявно обозначаются extern, если только они явно не помечены, например, static). Обратите внимание, что прототипы функций static не могут появляться внутри функции.

person Seth Carnegie    schedule 08.02.2012
comment
Статические прототипы функций не могут появляться внутри функции, вы имели в виду, что если bar является static, то я не могу предварительно объявить void bar(int); или static void bar(int); внутри foo? - person Alcott; 08.02.2012
comment
Однако вы не можете предварительно объявить функцию в другом пространстве имен. - person Ben Voigt; 08.02.2012
comment
@Alcott, вы не можете пересылать объявления static void bar(int); внутри foo. - person Seth Carnegie; 08.02.2012