声明但不定义内部结构/类 - 合法C++与否?

Sum*_*uma 8 c++ definition inner-classes forward-declaration

以下代码是否合法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);
}
Run Code Online (Sandbox Code Playgroud)

Visual C++和GCC都接受它,但是代码对我来说似乎有些奇怪,我不愿意让它被未来的编译器拒绝.

尽管如此,这种模式似乎对减少编译时依赖性很有用 - 我经常使用它来声明用于传递一些"上下文"(一堆变量)的结构,这些结构在一些函数之间共享,这些函数都位于同一个cpp中文件,这样我就不必将"上下文"定义引入公共接口.

sti*_*ijn 10

合法的,确实有用的隐藏实施细节到外面的世界.


zum*_*ard 9

[编辑]我最初说这是"pimpl成语":http://c2.com/cgi/wiki?PimplIdiom 但我同意这只是pimpl的一部分.pimpl使用这种技术.

你在Foo类中"转发"类Bar.完全合法,只要你在Foo的definigino中没有做任何需要尺寸Bar的东西.您可以使用指针或引用(Bar*或Bar&)引用Bar,但如果您在Foo中声明数据成员,例如:

私人:Bar _bar;

它不会起作用.原因是因为Foo的定义必须足以确定Foo的大小.由于Bar的大小在Foo的定义中是未知的,因此会使Foo的大小不确定.但是使用指针会起作用:

私人:Bar*_bar;

因为指针的大小是相同的,因此是已知的,无论后来如何定义Bar.

  • 好吧,它不是_exactly_ pimpl成语(他的代码中没有pimpl),但你是对的 - 实际上它是.+1 (2认同)