我偶然碰巧在我看到的一个源代码中找到了这个。所以,我在这里给出了一个类似的小例子。
在文件 test.h :
中#include<iostream>
class test{
int i;
public:
test(){}
//More functions here
};
在文件 test.cpp :
中#include "test.h"
int main()
{
test test1;
test::test test2;
test::test::test test3;
return 0;
}
首先,有理由以这种方式宣布test2
吗?其次,这个代码在g ++ 4.4.3版和更低版本中编译得很好。 C ++标准中有什么东西说,当不需要解析范围时,范围解析运算符会被忽略吗?
答案 0 :(得分:41)
此代码无效。
g ++中的错误是它接受了代码。请参阅"g++ does not treat injected class name correctly."该错误已于2009年解决,因此应在任何最新版本的g ++中修复。
答案 1 :(得分:16)
澄清情况,如§9/ 2中所述:
在看到类名后立即将类名插入到作用域中。类名也插入到类本身的范围内;这被称为注入类名。出于访问检查的目的,inject-class-name被视为公共成员名称。
但是,如§3.4.3.1/ 1中所述:
如果qualified-id的nested-name-specifier指定了一个类,则在类(10.2)的范围内查找在嵌套的namespecifier之后指定的名称,但下面列出的情况除外。
[......§3.4.3.1/ 2]:
在查找中,构造函数是可接受的查找结果,而嵌套名称说明符指定类C:
- 如果在C中查找的nested-name-specifier之后指定的名称是C的注入类名(第9条)[...],则该名称被认为是命名构造函数的名称。 C级。
[...例如:]
struct A { A(); };
[ ... ]
A::A a; // error, A::A is not a type name
struct A::A a2; // object of type A