C++ 将内部类名声明为另一个声明的一部分
在试图用pimpl习惯用法定义一个类时,我试图通过将类前向声明滚动到pimpl定义中来保存一行代码C++ 将内部类名声明为另一个声明的一部分,c++,language-lawyer,C++,Language Lawyer,在试图用pimpl习惯用法定义一个类时,我试图通过将类前向声明滚动到pimpl定义中来保存一行代码 class A { public: class Impl *pimpl; }; 上述声明汇编得很好。不起作用的是试图定义A::Impl: 结果是: 错误:限定名未在“{”标记之前命名类 现在,我们可以通过一个复杂的类型说明符引入一个新的类名,作为另一个声明的一部分 为什么在它自己的行上的前向声明(如惯用用法)会引入a::Impl,但在作为指针定义的一部分声明时,会引入::Impl 更新
class A
{
public:
class Impl *pimpl;
};
上述声明汇编得很好。不起作用的是试图定义A::Impl
:
结果是:
错误:限定名未在“{”标记之前命名类
现在,我们可以通过一个复杂的类型说明符引入一个新的类名,作为另一个声明的一部分
为什么在它自己的行上的前向声明(如惯用用法)会引入a::Impl
,但在作为指针定义的一部分声明时,会引入::Impl
更新
我不是问如何让这个成语起作用,我的问题是为什么要用单行
class Impl *pimpl;
不具有与两行相同的效果
class Impl;
Impl *pimpl;
在类定义的上下文中
class A
{
public:
class Impl *pimpl;
};
我很困惑,因为这个名字在使用时就被正确地限定了
稍微更改您的
A
声明:
class A
{
public:
class Impl;
Impl *pimpl;
};
现在,一切都将按预期进行
首先,您必须告诉编译器,Impl
是一个内部类
class A
{
public:
class Impl *pimpl;
};
这告诉编译器,
pimpl
是一个指向名为Impl
的顶级类的指针,而不是一个内部类。好吧,标准像往常一样提供了一个答案。并明确要求它
引述第2款(empahsis矿):
如果详细类型说明符没有嵌套的名称说明符,则为,除非详细类型说明符以以下形式出现在声明中:
类键属性说明符seqopt标识符
根据[basic.lookup.unqual]查找标识符,但忽略已声明的任何非类型名称(…)
如果详细类型说明符是由类键引入的,并且此查找未找到以前声明的类型名称,或者如果详细类型说明符以以下形式出现在声明中: 类键属性说明符seqopt标识符 详细说明的类型说明符是一个声明,它引入了类名称,如[basic.scope.pdecl]中所述 和第7段(再次强调): 在详细的类型说明符中首先声明的类的声明点如下: --申请表格的声明 类键属性说明符seqopt标识符 标识符被声明为包含该声明的作用域中的类名,否则 --对于窗体的详细类型说明符 类密钥标识符 如果在命名空间范围中定义的函数的decl说明符seq或参数声明子句中使用了详细的类型说明符,则标识符将在包含该声明的命名空间中声明为类名;否则,除了作为友元声明外,标识符将在最小的名称中声明包含声明的espace或block作用域[注意:这些规则也适用于模板。-结束说明][注意:其他形式的详细类型说明符不声明新名称,因此必须引用现有类型名称。请参阅[basic.lookup.elab]和[dcl.type.elab]。-结束说明] 最后一行强调的声明似乎是指出现详细类说明符的类的声明。因此,在我们的示例中,它将
Impl
添加到包含类A
的命名空间中,即全局范围。但这同样适用于任何命名空间:
我知道如何使它按预期工作。这不是我的问题。我想我应该删除
pimpl
标记。
class A
{
public:
class Impl;
Impl *pimpl;
};
class A
{
public:
class Impl *pimpl;
};
namespace E
{
class A
{
class Impl *pImpl;
};
}
class E::Impl
{
};
int main() {
// your code goes here
return 0;
}