8

以下代码是否合法 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 中文件,这样我就不必将“上下文”定义引入公共接口。

4

2 回答 2

10

合法,并且确实有助于向外界隐藏实现细节。

于 2009-10-14T07:51:04.397 回答
9

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

您正在 Foo 类中“转发”类 Bar。只要您不在 Foo 的定义中执行任何需要 sizeof Bar 的操作,就完全合法。您可以使用指针或引用(Bar* 或 Bar&)来引用 Bar,但如果您在 Foo 中声明一个数据成员,例如:

私人:酒吧_bar;

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

私人:酒吧* _bar;

因为指针的sizeof是相同的,因此是已知的,不管Bar后面怎么定义。

于 2009-10-14T08:00:02.213 回答