命名空间范围构造函数定义是否需要类限定标识符?

时间:2011-08-19 09:14:29

标签: c++ syntax constructor

这是我们在C ++第1天学到的东西,我们认为这是理所当然的,但并没有明确遵循标准的措辞。

给定一个类S,我们可以定义它的构造函数

struct S { S(); };
S::S() { … }

但标准似乎也允许这样做:

struct S { S(); };
S() { … }

始终允许使用自身限定类的名称,但始终是多余的。例如,S::S::S::S() { … }也是一个有效的声明。如果是S::S,为什么不明白S

来自C ++11§12.1/ 1,

  

构造函数没有名称。特殊的声明符语法用于声明或定义构造函数。语法使用:

     

- 一个可选的decl-specifier-seq,其中每个decl-specifier都是一个函数说明符或constexpr,

     

- 构造函数的类名和

     

- 参数列表

     按顺序

这同样适用于类或命名空间范围。有关命名空间范围的特殊规则,§9.3/ 5,

  

如果成员函数的定义在词法定义之外是词法定义,则成员函数名称应使用::运算符通过其类名限定。

但是,构造函数没有名称,所以这不适用,对吧?而且,没有理由要求资格,因为没有语法歧义。在当前观察到的规则下,声明为没有返回类型和标识符的类名的函数始终是语法错误。正确?

不是我们应该开始编写省略资格的代码,但是有没有编译器接受这个的原因,或者它只是传统吗?

3 个答案:

答案 0 :(得分:3)

是的,它说,

  

如果成员函数的定义在词法定义之外是词法上的     成员函数名称应使用:: operator。

通过其类名限定

表示没有名称的会员功能 由其认可班级名称。可以? ;)

根据实施情况,这似乎会导致不确定的区域。但是,A :: A的形式由标准定义。

5.1主要表达

  

使用class-name :: class-name,并且两个类名引用同一个类,这个表示法命名构造函数。

关于是否允许A(){..},我想没有理由按常规进行(是否有任何C ++编译器允许它?AFAIK,nope):

  1. 由于构造函数是一个特殊的成员函数,A::A(){..}的方式与其他成员函数更加一致。为什么borther允许它特别表现?这可能不值得付出努力。

  2. 没有人愿意承担编写标准中未明确规定的不合规代码的风险。

答案 1 :(得分:1)

当在命名空间范围内遇到令牌S() { }时,编译器不能神奇地决定它是一个ctor。哪种语法规则会产生这样一系列令牌?让我们忽略除函数定义之外的一切;他们不能产生( ){ }部分。

这意味着S()必须是声明符,而 decl-specifier-seq opt 必须为空(见§8.4.1)。 §9.2/ 7随后告诉我们声明符必须命名构造函数,析构函数或转换函数。但S也未命名。因此,S() { }无效。

答案 2 :(得分:1)

尽管这个问题在最初发布的 C++11 标准中充其量是模棱两可的,并且在这个问题出现时,Defect Resolution 1435 于 2013 年 4 月被接受,更改了相关文本,以便命名空间范围内的构造函数定义确实需要 qualified-id(使用 :: 的语法)作为“名称”。

C++14(或接近那个时间)中的同一段是:

<块引用>

构造函数没有名字。构造函数的声明使用形式为

的函数声明符 ([dcl.fct])

ptr-declarator ( parameter-declaration-clause ) 异常规范opt attribute-specifier-seqopt

其中 ptr-declarator 仅由一个 id-expression、一个可选的 attribute-specifier-seq 和可选的环绕括号组成,并且 id-expression 具有以下形式之一:

  • 在属于类的成员规范但不是友元声明([class.friend])的成员声明中, id-expression 是直接封闭类的注入类名([class]);
  • 在属于类模板的成员规范但不是友元声明的成员声明中,id-expression 是一个 class-name ,它命名直接封闭类模板的当前实例化 ([temp.dep.type]);或
  • 在命名空间范围的声明或友元声明中,id-expression 是一个 qualified-id,它命名一个构造函数 ([class.qual])。

这一段有一些更小的调整,没有改变这个问题的答案。 current version 内容如下:

<块引用>

declarator 声明一个 构造函数,如果它是一个函数声明符 ([dcl.fct])

ptr-declarator ( parameter-declaration-clause ) noexcept-specifieropt attribute-specifier-seqopt

其中 ptr-declarator 仅由一个 id-expression、一个可选的 attribute-specifier-seq 和可选的环绕括号组成,并且 id-expression 具有以下形式之一:

  • 在友元声明 ([class.friend]) 中,id-expression 是一个 qualified-id 命名构造函数 ([class.qual]);
  • 否则,在属于类或类模板的成员规范成员声明中,id-expression是直接封闭实体的注入类名称([class.pre]);
  • 否则,id-expression 是一个 qualified-id,其 unqualified-id 是其查找上下文的注入类名.

构造函数没有名字。 ...