【问题标题】:Declare but not define inner struct/class - legal C++ or not?声明但不定义内部结构/类 - 是否合法 C++?
【发布时间】:2009-10-14 07:42:29
【问题描述】:

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

【问题讨论】:

  • 我正在制作几个上下文类,所以我也很感兴趣。顺便说一句,让 countDrinks 公开访问。
  • 我是否正确地假设您指的是 class Foo::Bar 定义?

标签: c++ definition inner-classes forward-declaration


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    [编辑] 我最初说这是“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后面怎么定义。

    【讨论】:

    • 嗯,这不是完全 pimpl 习惯用法(他的代码中没有 pimpl),但你是对的 - 基本上是这样。 +1
    • 它仅与 pimpl 相关,因为它更多地与某些上下文的范围有关,其中 pimpl 是您的类的完整实现。但你是对的:你只能在这样做时声明一个指针。帮自己一个忙,使用适当的智能指针。
    • 这绝对不是 PIMPL。 Bar中没有实现。
    • 它通常与Pimpl结合使用,声明一个“Impl”类将用于实现,但它具有更广泛的应用范围(例如提到的上下文)。
    • 虽然这可能不是典型的 pimpl 实现,但在我看来它本质上是相同的。与普通 pimpl 惯用语的唯一区别是 Bar 不用于维护不同公共方法调用之间的状态。但是,如果类不需要在该范围内保持该状态,则没有理由保留它,因此没有理由在堆上动态分配它。
    猜你喜欢
    • 2023-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-09
    • 1970-01-01
    相关资源
    最近更新 更多