在类中的定义之前分析声明
Parsing declarations before definitions in a class
这个问题在这里激起了我的兴趣。C++标准中是否有任何地方指定在成员函数的任何随附实现之前必须解析类中的所有声明?我看到了其他一些与此类似的问题,但在任何答案中都没有提及该标准。
标准没有指定编译器应如何解析翻译单元。相反,它指定了使用任何标识符来引用声明的所有位置以及无效的位置。
3.3.2p5:
在类成员的声明点之后,可以在其范围内查找成员名称 类。 [ 注意:即使类是不完整的类,也是如此。
3.3.7p1:
以下规则描述类中声明的名称的范围。
- 在类中声明的名称的潜在作用域不仅包括名称声明点后面的声明性区域,还包括所有函数体、非静态数据成员的大括号或等于初始值设定项以及该类中的默认参数(包括嵌套类中的此类内容)。
- 类
N
中使用的名称S
应在其上下文中引用相同的声明,并在已完成的S
范围内重新评估时。对于违反此规则,无需进行诊断。- 如果对类中的成员声明重新排序在 (1) 和 (2) 下生成备用有效程序,则程序格式不正确,不需要诊断。
在成员函数- 中声明的名称隐藏其作用域扩展到或超过成员函数类末尾的相同名称的声明。
扩展到- 类定义末尾或超过类定义末尾的声明的潜在范围也会扩展到其成员定义定义的区域,即使成员在类之外以词法方式定义(这包括静态数据成员定义、嵌套类定义、成员函数定义(包括成员函数体和此类定义中此类定义中遵循声明符 id 的任何部分),包括参数声明子句和任何默认参数 (8.3.6)。
[class.mem] 说:
-2- 类在类说明符的结束
}
被视为完全定义的对象类型 (3.9)(或完整类型)。在类成员规范中,类在函数体、默认参数和非静态数据成员(包括嵌套类中的此类内容)的大括号或等于初始值设定项中被视为完整。否则,它在其自己的类成员规范中被视为不完整。
为了使类在函数体内完成,那么通常需要解析所有声明:如果不完全解析所有声明,您将无法知道未解析的内容是否会改变含义。 虽然,可能与此相关的是[basic.scope.class]/1,它说:
3) 如果对类中的成员声明重新排序会产生 (1) 和 (2) 下的备用有效程序,则程序格式不正确,不需要诊断。
这意味着可以在不解析整个类的情况下使用某些声明,因为如果另一个后来的声明改变了含义,那么程序的格式将不正确。
当然,"好像"规则允许编译器选择任何实现,只要用户无法分辨出区别,所以也许编译器可以选择解析函数体,然后根据需要解析定义,但很难说处理成员函数定义需要什么(考虑一个可能调用几个重载函数之一的函数调用, 可能涉及enable_if型技巧。
解释编程语言标准的草案C++。
编程语言 C++ PDF
我认为第 220 页对成员函数有一些解释。
- 如何在C++中声明/定义相互依赖的模板?
- C++概念是否允许我的类在声明/定义中指定它满足某些概念?
- MSVC:无法识别的模板声明/定义(使用 Clang/GCC 编译)
- 我可以重用同一个模板来声明/定义多个东西吗(而不复制模板代码)
- C++-模板类中模板函数的单独声明/定义
- 在C 中使用继承时,请避免使用未缴纳的函数声明/定义
- C++模板能否确定所声明/定义的实例是否为常量
- 如何在程序中声明/定义一次并在两个类中使用映射列表
- LBNF,C函数声明/定义,减少冲突
- 声明/定义返回具有自动返回类型的 valarray 的函数时的隔离错误
- #用{}和声明定义混淆
- CTOR 声明/定义中接受的 const 限定符(LLVM 错误?)
- C++ 从一个源文件中声明/定义的变量从另一个源文件访问另一个源文件
- 无法识别的模板声明/定义
- 只在.cpp中声明/定义静态方法可以吗
- 声明/定义自定义类定制对象的正确方法
- typedef声明定义未命名类时链接失败
- 用visual c++实现COM对象的声明/定义和实例化
- VS 2012中的显式模板声明/定义
- 命名空间内的友元函数声明/定义