为什么我不能使用双冒号在命名空间中转发声明一个类?

161 c++ namespaces

class Namespace::Class;
Run Code Online (Sandbox Code Playgroud)

我为什么要这样做?:

namespace Namespace {
    class Class;
}
Run Code Online (Sandbox Code Playgroud)

使用VC++ 8.0,编译器会发出:

错误C2653:'Namespace':不是类或命名空间名称

我假设这里的问题是编译器无法判断Namespace是类还是命名空间?但是为什么这很重要,因为它只是一个前瞻性声明?

是否有另一种方法来转发声明在某个命名空间中定义的类?上面的语法感觉就像我"重新打开"命名空间并扩展其定义.如果Class没有实际定义Namespace怎么办?这会在某个时候导致错误吗?

Joh*_*ing 196

你得到了正确的答案,让我试着重新措辞:

class Namespace::Class;

为什么我要这样做?

你必须这样做,因为这个术语Namespace::Class告诉编译器:

......好的,编译器.找到名为Namespace的命名空间,并在其中引用名为Class的类.

但编译器不知道你在说什么,因为它不知道任何命名空间Namespace.即使有一个命名空间Namespace,如:

namespace Namespace
{
};

class Namespace::Class;
Run Code Online (Sandbox Code Playgroud)

它仍然无法工作,因为您无法在该命名空间外部声明一个类.您必须在命名空间中.

因此,您实际上可以在命名空间中转发声明一个类.这样做:

namespace Namespace
{
    class Class;
};
Run Code Online (Sandbox Code Playgroud)

  • 所有其他答案都让我感到困惑,但是"你不能在命名空间外部声明一个类.你必须在命名空间中." 非常有帮助提醒要记住. (38认同)

AnT*_*AnT 83

因为你做不到.在C++语言中,完全限定名称仅用于引用现有(即先前声明的)实体.它们不能用于引入实体.

事实上,您正在 "重新打开"命名空间以声明新实体.如果该类Class稍后被定义为不同命名空间的成员 - 它是一个完全不同的类,与您在此处声明的类无关.

一旦达到定义预先声明的类的程度,就不需要再次"重新打开"命名空间.您可以在全局命名空间(或包含您的任何命名空间Namespace)中定义它

class Namespace::Class {
  /* whatever */
};
Run Code Online (Sandbox Code Playgroud)

由于您指的是已在命名空间中声明的实体,因此Namespace您可以使用限定名称Namespace::Class.

  • @STingRaySC:转发声明嵌套类的唯一方法是将声明放在封闭类的*definition*中.在封闭类的定义之前,确实无法向前声明嵌套类. (10认同)
  • @John Dibling:*嵌套类*是在另一个类中声明的类.直接在命名空间内声明的类不是嵌套类.你的答案中没有关于敏感课程的内容. (7认同)

Igo*_*aka 22

我想这是出于同样的原因,你不能像这样一次声明嵌套命名空间:

namespace Company::Communications::Sockets {
}
Run Code Online (Sandbox Code Playgroud)

你必须这样做:

namespace Company {
  namespace Communications {
    namespace Sockets {
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • C++ 17添加了这个. (15认同)
  • 这是一个节省了大量时间的答案 (6认同)
  • 这实际上并不是一个解释为什么你不能这样做的答案。 (3认同)

Mar*_*n G 10

尚不清楚前向声明变量的类型实际上是什么。前瞻性声明class Namespace::Class;可能意味着

namespace Namespace {
  class Class;
}
Run Code Online (Sandbox Code Playgroud)

要么

class Namespace {
public:
  class Class;
};
Run Code Online (Sandbox Code Playgroud)

  • 我认为这是最好的答案之一,因为它回答了为什么编译器本身不容易确定的原因。 (5认同)