2016-05-13 70 views
2

当试图通过pimpl习语定义一个类时,我尝试通过将类向前声明滚动到pimpl定义来保存一行代码。声明内部类名称作为另一个声明的一部分

class A 
{ 
public: 
    class Impl *pimpl; 
}; 

上述声明编译得很好。什么不起作用,是定义A::Impl的尝试。 As the program bellow demonstrates

class A 
{ 
public: 
    class Impl *pimpl; 
}; 

class A::Impl 
{ 

}; 

int main() { 
    // your code goes here 
    return 0; 
} 

它与结果:

error: qualified name does not name a class before '{' token

现在,一个可以引入新的班级名称,由一个复杂的类型说明,作为另一个声明的一部分。但实际上Class ::Impl就是introduced

class A 
{ 
public: 
    class Impl *pimpl; 
}; 

class Impl 
{ 

}; 

int main() { 
    Impl i; 
    A a; 
    a.pimpl = &i; 
    return 0; 
} 

为什么是它在它自己的行前向声明(如成语经常使用),将引进A::Impl,但作为指针定义的一部分声明时,将引入::Impl

更新

我不问如何使成语工作。我的问题是,为什么单行

class Impl *pimpl; 

没有因为两行

class Impl; 
Impl *pimpl; 

在一个类定义的情况下相同的效果。

我很困惑,因为名字在something similar is done in the context of a namespace时变得合格。

namespace A 
{ 
    class Impl *pimpl; 
}; 

class A::Impl 
{ 

}; 

int main() { 
    // your code goes here 
    return 0; 
} 

回答

0

那么,标准提供了一个像往常一样的答案。并明确规定。

报价3.4.4 [basic.lookup.elab]第2款(empahsis矿):

If the elaborated-type-specifier has no nested-name-specifier, and unless the elaborated-type-specifier appears in a declaration with the following form:

class-key attribute-specifier-seqopt identifier ;

the identifier is looked up according to [basic.lookup.unqual] but ignoring any non-type names that have been declared
(...)
If the elaborated-type-specifier is introduced by the class-keyand this lookup does not find a previously declared type-name, or if the elaborated-type-specifier appears in a declaration with the form:

class-key attribute-specifier-seqopt identifier ;

the elaborated-type-specifier is a declaration that introduces the class-name as described in [basic.scope.pdecl].

而且3.3.2 [basic.scope.pdecl]第7段(重点再次回到我的):

The point of declaration of a class first declared in an elaborated-type-specifier is as follows:

-- for a declaration of the form

class-key attribute-specifier-seqopt identifier ;

the identifier is declared to be a class-name in the scope that contains the declaration, otherwise

-- for an elaborated-type-specifier of the form

class-key identifier

if the elaborated-type-specifier is used in the decl-specifier-seq or parameter-declaration-clause of a function defined in namespace scope, the identifier is declared as a class-name in the namespace that contains the declaration; otherwise, except as a friend declaration, the identifier is declared in the smallest namespace or block scope that contains the declaration. [ Note: These rules also apply within templates. — end note ] [ Note: Other forms of elaborated-type-specifier do not declare a new name, and therefore must refer to an existing type-name. See [basic.lookup.elab] and [dcl.type.elab]. — end note ]

在最后强调线上的声明似乎是指详细说明的类说明符出现的类的声明。所以在我们的例子中,它将Impl添加到包含全局作用域A的名称空间中。但是这同样适用于任何命名空间。 Case and point

namespace E 
{ 
    class A 
    { 
     class Impl *pImpl; 
    }; 
} 

class E::Impl 
{ 

}; 

int main() { 
    // your code goes here 
    return 0; 
} 
5

稍微改变你的A声明:

class A 
{ 
public: 
    class Impl; 

    Impl *pimpl; 
}; 

现在,预计一切都将正常工作。

您必须先告诉编译器Impl是内部类。

class A 
{ 
public: 
    class Impl *pimpl; 
}; 

这告诉编译器pimpl是一个指向名为Impl一些顶级类,而不是一个内部类。

+0

我知道如何让它按预期工作。这不是我的问题。我想我应该删除'pimpl'标签。 – StoryTeller

相关问题