内部成员在课堂上的可见度

时间:2015-11-25 03:10:30

标签: c++ language-lawyer

根据C ++标准,

  

9.2 [class.mem]:

     

一个类被认为是一个完全定义的对象类型(3.9)(或   完成类型)在类说明符的结束时。内   class member-specification,该类被认为是完整的   函数体,默认参数,引用的使用声明   继承构造函数(12.9),异常规范和   用于非静态数据成员的括号或等于初始化器(包括   嵌套类中的这类东西)。否则它被认为是不完整的   在其自己的类成员规范

所以,下面的代码应该编译,确实是

struct Foo{
     Foo()
     {
        Bar bar; // Bar is fully visible here, even though it's defined later
     }
     //void f(Bar){} // But NOT VISIBLE if used as a function parameter
     struct Bar{};
};

int main()
{
    Foo foo;
}

Live on Coliru

但是,如果我取消注释定义成员函数void Foo::f(Bar)的行,则代码无法使用错误进行编译

  

错误:' Bar'尚未宣布

再次阅读标准确实似乎函数参数不被视为类被视为完整的地方。但是,它根本没有任何意义。您能否解释为什么我不能在函数参数中使用Bar(但在其完全定义之前可以完全使用函数中没有任何问题)?

2 个答案:

答案 0 :(得分:6)

9.2 [class.mem] 中列出的所有情况中,知道类型可以延迟到完全定义类之前。我们可以在defect report 643: Use of decltype in a class member-specification中找到这样的理由:

  

在类的定义中认为类类型完整的其他情况下,可以将处理构造推迟到定义的结尾。这对于类型是不可能的,因为在后续声明中可能需要立即使用类型。

作为T.C.指出在defect report 325: When are default arguments parsed?defect report 1352处理时还存在查找问题。后者还提到了能够推迟解析直到课程完成的相同技术:

  

关于类范围的规则以及何时认为类是完整的(通常通过对类成员声明的部分进行延迟解析来实现)是不一致的,需要澄清。

答案 1 :(得分:2)

从03标准,3.4.1 / 8(非限定名称查找):

  

在函数的declarator-id 29 之后的类X的成员函数(9.3)的定义中使用的名称   应以下列方式之一宣布:

     

- 在使用它之前的块中或在封闭块(6.3)中,或

     

- 应该是X类成员或者是X(10.2)基类的成员,或者

     

- 如果X是Y类(9.7)的嵌套类,则应为Y的成员,或者是Y的基类的成员   (这个查找依次应用于Y的封闭类,从最里面的封闭类开始),30)或

     

- 如果X是本地类(9.8)或是本地类的嵌套类,则在块中定义类X之前   包含类X的定义,或

     

- 如果X是名称空间N的成员,或者是属于N的成员的类的嵌套类,或者是本地类   或者在成员函数之前,作为N的成员的函数的本地类中的嵌套类   定义,在命名空间N或N的封闭命名空间之一。