Ошибка компиляции C ++ enum "не называет тип" - PullRequest
4 голосов
/ 27 октября 2010

Следующий код:

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 "не называет тип".Зачем ?Все заголовки имеют множественные определения включения (здесь не показаны для ясности).

Спасибо

Ответы [ 3 ]

4 голосов
/ 27 октября 2010

Проблемы:

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

Ваш 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 идиома .

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

2 голосов
/ 27 октября 2010

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

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

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

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

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

2 голосов
/ 27 октября 2010
foo()
{
   int i = bar::MY_DEFINE;
}

должно быть

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

Также обратите внимание, что

static const int MY_DEFINE = 10;

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

const int bar::MY_DEFINE;

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...