类中的内部成员可见性
Inner member visibility in class
根据C++标准,
9.2[class.mem]:
类被视为完全定义的对象类型(3.9)(或完整类型)。在类成员规范,该类在函数体,默认参数,使用引入继承构造函数(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;
}
在Coliru上直播
但是,如果我取消注释定义成员函数void Foo::f(Bar)
的行,则代码编译失败,并出现错误
错误:"Bar"尚未声明为
再次阅读标准,函数参数似乎确实不被视为类完整的地方。然而,这根本没有任何意义。你能解释一下为什么在函数参数完全定义之前,我不能在函数参数中使用Bar
(但在其他情况下,我可以在函数内部完全使用它,而不会有任何问题)吗?
在9.2
[class.mem]中列出的所有情况下,知道类型可以推迟到类完全定义为止。我们可以在缺陷报告643中看到这一基本原理:在类成员规范中使用decltype,其中写道:
在其他情况下,如果类类型在类的定义中被认为是完整的,则可以将处理构造推迟到定义结束。这对于类型来说是不可能的,因为在随后的声明中可能会立即需要该类型。
正如T.C.所指出的,缺陷报告325也涉及查找问题:默认参数何时解析?并且缺陷报告1352进行处理。后面的一个还提到了能够推迟解析直到类完成的相同技术:
关于类作用域和类何时被认为是完整的规则(通常通过延迟解析类成员声明的部分来实现)是不一致的,需要澄清。
根据03标准,3.4.1/8(不合格名称查找):
定义X类成员函数(9.3)时使用的名称,该函数的声明符id29)应以以下方式之一声明:
--在使用它的块中或在封闭块(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的封闭名称空间之一中
- 如何更改唯一指针向量的可见性
- 当指向对象的指针作为参数传递给 std::thread 时,内存可见性
- 限制静态库中符号的可见性 (MSVC/Visual C++)
- 班级成员可见性C++
- 内联模板函数的可见性
- Clang 是否可以在使用可见性属性时生成导入库(不带 __declspec(dllexport))?
- std::mutex 的发布-获取可见性保证是否仅适用于关键部分?
- 符号可见性和 gcc 警告
- C++/libscreen 无法更新可见性
- 在 C++11 线程中,std::mutex 对内存可见性有什么保证?
- C++继承构造函数的可见性
- CRTP - 嵌套叶类类型的可见性
- C++模板 - 实例之间的通用操作和成员可见性
- 未直接继承的基模板类成员的可见性
- 关于Lambdas,转换以功能指针以及私人数据成员的可见性
- 成员函数声明签名中的类成员可见性
- 更改类模板成员可见性
- 为什么可以更改虚拟成员或公共基类的可见性
- 在C++中,do访问说明符不控制静态成员的可见性
- 类中的内部成员可见性