2012-06-06 2 views
3

Я занимаюсь программированием на C++ в течение некоторого времени, и я никогда не думал об этом до сегодняшнего дня.Почему в C++ не задан порядок методов в классе?

Рассмотрим следующий код:

struct foo 
{ 
    // compiles fine 
    void bar() 
    { 
    a = 1; 
    my_int_type b; 
    b = 5; 
    } 

    // Just a declaration, this fails to compile, which leads me to assume that 
    // even though the bar() method is declared and defined all at once, the 
    // compiler looks/checks-syntax-of the class interface first, and then compiles 
    // the respective definitions...? 
    void bar2(my_int_type); // COMPILE ERROR 

    my_int_type  b; // COMPILE ERROR because it comes before the typedef declaration 
    typedef int  my_int_type; 
    my_int_type  a; 

    void bar3(my_int_type); // compiles fine 
}; 

int main() 
{ 
    foo a; 
    a.bar(); 
    return 0; 
} 

мое понимание того, почему возникают ошибки (см bar2() комментарий выше) правильно/неправильно? В любом случае, я был бы признателен за упрощенное описание того, как однопроходный компилятор C++ будет компилировать приведенный выше код.

+0

Довольно уверен, что я задал этот вопрос раньше ... :-) – Mehrdad

+0

@Mehrdad: Я искал его, но не смог найти его с ключевыми словами, которые пришли мне на ум :) – Samaursa

ответ

10

По большей части, файл C++ анализируется сверху вниз, поэтому сущности должны быть объявлены до их использования.

В вашем классе bar2 и b недействительны, так как оба они используют my_int_type, который еще не был объявлен.

Единственное исключение из правила синтаксического анализа «сверху вниз» - это функции-члены, которые определены внутри определения их класса. Когда такое определение функции члена анализируется, оно анализируется так, как если бы оно появилось после определения класса. Вот почему ваше использование my_int_type в bar действительно.

Фактически, это:

struct foo 
{ 
    void bar() 
    { 
     my_int_type b; 
    } 

    typedef int my_int_type; 
}; 

так же, как:

struct foo 
{ 
    void bar(); 

    typedef int my_int_type; 
}; 

inline void foo::bar() 
{ 
    my_int_type b; 
} 
5

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

Вы можете предположить, что компилятор сначала делает список определений, поэтому метод bar() должен быть скомпилирован правильно, поскольку ранее были предоставлены определения.

3

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

  1. Определение класса анализа.
  2. Реализация метода анализа.

Преимущество этого в том, что у нас есть видимость всего класса изнутри функций класса.

Смежные вопросы