代码之家  ›  专栏  ›  技术社区  ›  user12345

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

  •  148
  • user12345  · 技术社区  · 16 年前
    class Namespace::Class;
    

    我为什么要这么做?以下内容:

    namespace Namespace {
        class Class;
    }
    

    使用VC++8.0,编译器问题:

    错误C2653:“命名空间”:不是类或命名空间名称

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

    是否有其他方法来转发声明在某些命名空间中定义的类?上面的语法让我感觉像是在“重新打开”名称空间并扩展其定义。如果…怎么办 Class 实际上在 命名空间 ?这会在某一点上导致错误吗?

    5 回复  |  直到 7 年前
        1
  •  79
  •   AnT stands with Russia    11 年前

    因为你不能。在C++语言中,完全限定的名称仅用于引用。 现有的 (即先前声明的)实体。不能用来介绍 新的 实体。

    你呢 实际上,“重新打开”命名空间以声明新实体。如果上课 Class 稍后定义为不同命名空间的成员-它是一个完全不同的类,与您在此处声明的类无关。

    一旦你达到目的 定义 预先声明的类,不需要再次“重新打开”命名空间。您可以在全局命名空间(或包含您的 Namespace 作为

    class Namespace::Class {
      /* whatever */
    };
    

    因为您所引用的实体已在命名空间中声明 命名空间 ,可以使用限定名 Namespace::Class .

        2
  •  179
  •   meJustAndrew    8 年前

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

    class Namespace::Class;

    我为什么要这么做?

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

    …好的,编译器。去找 名为命名空间的命名空间,并且在 指的是名为class的类。

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

    namespace Namespace
    {
    };
    
    class Namespace::Class;
    

    它仍然不起作用,因为您不能在命名空间内从该命名空间之外声明类。您必须在命名空间中。

    所以,实际上,您可以在名称空间中向前声明一个类。只要这样做:

    namespace Namespace
    {
        class Class;
    };
    
        3
  •  19
  •   Omer Mor    12 年前

    我想这也是您不能像这样一次声明嵌套命名空间的原因:

    namespace Company::Communications::Sockets {
    }
    

    你必须这样做:

    namespace Company {
      namespace Communications {
        namespace Sockets {
        }
      }
    }
    
        4
  •  2
  •   Martin G    7 年前

    不清楚正向声明变量的类型实际上是什么。远期申报 class Namespace::Class; 可能意味着

    namespace Namespace {
      class Class;
    }
    

    class Namespace {
    public:
      class Class;
    };
    
        5
  •  0
  •   StoryTeller - Unslander Monica    8 年前

    关于拒绝的理由,有很多很好的答案。我只想提供无聊的标准条款,具体禁止它。这对于C++ 17(N465)是成立的。

    有问题的段落是 [class.name]/2 :

    仅由以下部分组成的声明 类键标识符 要么是 在当前作用域或转发中重新声明名称 将标识符声明为类名。它介绍了这门课 当前作用域中的名称。

    上面定义了什么构成了正向声明(或类的重新声明)。本质上,它必须是 class identifier; , struct identifier; union identifier; 在哪里? 识别器 常见的词汇定义 [lex.name] :

    identifier:
      identifier-nondigit
      identifier identifier-nondigit
      identifier digit
    identifier-nondigit:
      nondigit
      universal-character-name
    nondigit: one of
      a b c d e f g h i j k l m
      n o p q r s t u v w x y z
      A B C D E F G H I J K L M
      N O P Q R S T U V W X Y Z _
    digit: one of
      0 1 2 3 4 5 6 7 8 9
    

    这是通用方案的产物 [a-zA-Z_][a-zA-Z0-9_]* 我们都很熟悉。如你所见,这排除了 class foo::bar; 作为有效的转发声明,因为 foo::bar 不是标识符。它是一个完全限定的名字,有些不同。

    推荐文章