Поиск имени внутри списка параметров функции-члена

typedef int abc;

class Some{
   public:
      abc foo(){...}
      typedef double abc;
};

В приведенном выше коде я получаю сообщение об ошибке:

error: changes meaning of 'abc' from 'typedef int abc'

потому что в книге С++ учебник, пятое издание сказано:

Определения классов обрабатываются в два этапа:

1. Сначала компилируются декларации элементов.

2. Тела функций компилируются только после просмотра полного класса.

Но в коде здесь:

typedef int abc;

class Some{
     public:
        int foo(abc){...}
        typedef double abc;
};

Я установил abc в списке параметров. Но я не получил такой ошибки, и компилятор работает отлично. почему последний код не вызовет у меня никаких ошибок, подобных первому?


person longtengaa    schedule 20.03.2013    source источник
comment
Каков твой вопрос?   -  person Oswald    schedule 20.03.2013


Ответы (4)


Я не думаю, что есть какая-то причина. Эта ошибка не требует диагностики (в соответствии со стандартом C++), поэтому ее поведение фактически неопределенно, если эта ошибка присутствует в вашем коде.

Ваш компилятор просто не проверил список параметров на наличие этой ошибки, но вполне мог это сделать.

person Johannes Schaub - litb    schedule 09.05.2013

Вам нужно его квалифицировать, Some::abc:

typedef int abc;

class Some{
   public:
      Some::abc foo(){...}
      typedef double abc;
};
person Peter Wood    schedule 20.03.2013
comment
Да, я знаю. Но я спрашиваю здесь, почему последний код не вызывает ошибку, как это делал первый. - person longtengaa; 20.03.2013
comment
Если вы хотите знать, почему последний код не вызывает ошибку, как первый, вы должны указать это в вопросе, а не в комментарии к ответу. - person Oswald; 20.03.2013

Причина, по которой первый пример выдает ошибку, заключается в том, что при поиске имени не учитывается возвращаемый тип. Но когда фактическое тело функции генерируется в выражении, где оно вызывается, компилятор будет использовать Some::abc и найдет несоответствие.

typedef int abc;

class Some{
   public:
      abc foo() { return abc(); }  // during lookup/resolution, "abc" is known to be int, return type is not considered
      typedef double abc;
};

int main() 
{ 
    Some s; 
    int x = s.foo(); // kaboom, return type is double.
}

Во втором примере переопределение типа не имеет значения, потому что во время поиска имени abc известно как int, потому что определение внутреннего typedef еще не было просмотрено. Нет никаких последствий во время создания экземпляра функции на месте вызова, потому что возвращаемый тип также является int. Просто несоответствия нет.

typedef int abc;

class Some{
   public:
      int foo(abc) { return int(); }  // during lookup/resolution, "abc" is known to be int
      typedef double abc;             // this will not have been seen yet in the previous line
};

int main() 
{ 
    Some s; 
    int x = 0;
    s.foo(x); // OK, x is of type int
}
person TemplateRex    schedule 09.05.2013
comment
Но разве тело функции не должно быть скомпилировано после просмотра всего класса? - person longtengaa; 29.05.2013

В MinGW, если возвращаемый тип функции-члена отображается как тип псевдонима, определенный объявлением typedef. Не допускается изменение его значения. Правило поиска имени, которое вы запрашиваете, по-прежнему действует, как обычно, введенное в Lippman's C++ Primer на странице 447 - поиск имени для объявлений членов класса.

  1. Учитываются объявления членов класса, которые появляются перед использованием имени.
  2. Если поиск на шаге 1 не увенчался успехом, рассматриваются объявления, которые появляются в области, в которой определен класс, и которые появляются перед самим определением класса.
person Life    schedule 20.01.2014