Объявлять, но не определять внутреннюю структуру / класс - легально C ++ или нет?

StackOverflow https://stackoverflow.com/questions/1564817

Вопрос

Является ли следующий код легальным на C ++ или нет?

class Foo
{
  class Bar;

  void HaveADrink(Bar &bar);
  void PayForDrinks(Bar &bar);

  public:
  void VisitABar(int drinks);
};

class Foo::Bar
{
  public:
  int countDrinks;
};

void Foo::HaveADrink(Bar &bar)
{
  bar.countDrinks++;
}
void Foo::PayForDrinks(Bar &bar)
{
  bar.countDrinks = 0;
}
void Foo::VisitABar(int drinks)
{
  Bar bar;
  for (int i=0; i<drinks; i++) HaveADrink(bar);
  PayForDrinks(bar);
}

И Visual C ++, и GCC принимают это, однако код кажется мне несколько странным, и я бы не хотел, чтобы какой-нибудь будущий компилятор отказался от него.

Тем не менее, шаблон кажется мне полезным для уменьшения зависимостей во время компиляции - я часто использую его для объявления структур, которые используются для передачи некоторого "контекста" (набора переменных), которые совместно используются несколькими функциями, которые все находятся в одном cpp-файле, и таким образом мне не нужно вводить определение "контекста" в общедоступный интерфейс.

Это было полезно?

Решение

законно и действительно полезно скрывать детали реализации от внешнего мира.

Другие советы

[редактировать] Изначально я сказал, что это "идиома pimpl". : http://c2.com/cgi/wiki ?ПимплИдиом но я согласен, что это всего лишь часть того, о чем говорит pimpl.Эта техника используется компанией pimpl.

Вы "перенаправляете" класс Bar внутрь класса Foo.Совершенно законно до тех пор, пока вы ничего не делаете внутри definigino Foo, для чего потребовался бы sizeof Bar .Вы можете ссылаться на панель, используя указатель или ссылку (Bar* или Bar&), но если вы объявите элемент данных в Foo, такой как этот:

Частное:Бар _bar;

Это бы не сработало.Причина в том, что определения Foo должно быть достаточно для определения размера Foo .Поскольку размер Bar неизвестен внутри определения Foo, это сделало бы размер Foo неопределенным.Но использование указателя сработало бы:

Частное:Бар* _bar;

Потому что размер указателя одинаков и, следовательно, известен, независимо от того, как Bar будет определен позже.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top