2010-10-27 2 views
2

Следующий код:C++ Ошибка компиляции перечисление "не называет тип"

foo.h

#include "bar.h" 
class foo{ 
public: 
    enum my_enum_type { ONE, TWO, THREE }; 
    foo(); 
    ~foo() {} 
}; 

foo.cpp

foo::foo() 
{ 
    int i = bar::MY_DEFINE; 
} 

bar.h

#include "foo.h" 
class bar{ 
public: 
    static const int MY_DEFINE = 10; 
    foo::my_enum_type var; 
    bar() {}; 
    ~bar() {}; 
}; 

Делает компилятор g ++ жалуется на my_enum_type "не называет тип". Почему? Все заголовки имеют множественное включение (не показано здесь для ясности).

Благодаря

+1

Это должно работать нормально ... –

+1

Как вы используете классы? У вас еще нет исходного файла. Можете ли вы поделиться тем, как вы используете эти классы? –

+1

Спасибо, ребята, вы заставляете меня понять, что проблема не в синтаксисе, а в том, как я использовал классы. В foo.h было #include "bar.h", я заменил его на декларацию вперед, и теперь все в порядке! –

ответ

2

Вы должны удалить циклическая зависимость, поэтому вам нужно рассмотреть foo.cpp и foo.h как разные единицы для этой цели.

  • определение класса бара должно отображаться foo :: my_enum_type, поэтому, вероятно, bar.h, включая foo.h, является необходимостью.

  • определение класса Foo не использует какой-либо из бара, так foo.h не нужно включать bar.h

  • foo.cpp действительно нужно видеть планку для MY_DEFINE так foo.cpp должна включать в себя бар. час Это фактически также приведет к foo.h автоматически, но вы можете включить его в любом случае в foo.cpp, на случай, если позже вы удалите зависимость.

Предположительно, у ваших заголовков есть несколько охранников.

+1

Я не знал, что вам нужно учитывать зависимость .h и .cpp отдельно. Я думал, что более одного .h в .cpp был плохим дизайном. Вероятно, я ошибался, ваш ответ решает мою проблему. Благодаря :) –

4

Проблем:

  • нет нескольких защит включения
  • циклического включения
  • использования
  • типа до его декларации, вызванное циклическим включением

Вашего foo.h обрабатываемое препроцессором C выглядит как бесконечная пустая последовательность строк.

С нескольких foo.h защиты включения предобработан в:

> cpp foo.h 
class bar{ // preprocessed from #include "bar.h" 
public: 
    static const int MY_DEFINE = 10; 
    foo::my_enum_type var; 
    bar() {}; 
    ~bar() {}; 
}; 
// end of #include "bar.h" 
class foo{ 
public: 
    enum my_enum_type { ONE, TWO, THREE }; 
    foo(); 
    ~foo() {} 
}; 

Это, очевидно, не является допустимым C++ кода - Foo используются в барах тела без предварительного объявления. C++, в отличие от Java, требует, чтобы типы были объявлены перед использованием.

  • Используйте множественную защиту включения. В зависимости от вашей платформы это могут быть #ifndef макросы или #pragma once директивы
  • Удалить bar.h включение от foo.h.
  • Разместить переадресацию там, где это необходимо (в вашем случае bar может быть объявлено в foo.h, ваш пример не показывает необходимости в этом).
  • Переместите как можно большую реализацию в файлы * .cpp.

Если ситуация не может быть решена с помощью этих рекомендаций, используйте PIMPL idiom.

Короче - просто удалить #include "bar.h" директиву из foo.h

+0

Мои заголовки имеют множественную защиту включения. Если я удалю bar.h из foo.h, foo.cpp больше не сможет использовать bar :: MY_DEFINE («bar» не был объявлен). –

+0

Неправильно. foo.cpp все равно может использовать bar, если вы включите bar.h в foo.cpp. – Basilevs

+0

Да, это то, чего я не знал;) –

2
foo() 
{ 
    int i = bar::MY_DEFINE; 
} 

должен быть

foo::foo() 
{ 
    //... 
} 

Также отметим, что

static const int MY_DEFINE = 10; 

еще заявление, хотя оно имеет инициализатор. В баре.CPP вы должны иметь следующую строку

const int bar::MY_DEFINE; 

Также вы не можете включить bar.h из foo.h и foo.h от bar.h ... это физически невозможно :)

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