cod*_*r2k 4 c++ constructor function member-functions language-lawyer
来自C++标准工作草案:
默认构造函数 ([class.default.ctor])、复制构造函数、移动构造函数 ([class.copy.ctor])、复制赋值运算符、移动赋值运算符 ([class.copy.assign]) 和预期析构函数 ([class .dtor])是特殊成员函数。
(https://eel.is/c++draft/special)
给出以下代码:
struct S {
S(int, float, double);
};
Run Code Online (Sandbox Code Playgroud)
在我的理解中, 的构造函数S不是特殊的成员函数,因为它既不是默认构造函数,也不是复制构造函数,也不是移动构造函数。
我想知道标准是否仍然认为构造函数是成员函数(或“唯一”的东西)。
我阅读了 C++ 工作草案中有关成员函数、特殊成员函数和构造函数的部分,但没有找到任何合理的答案来回答这个问题。我还查看了 StackOverflow,但大多数答案都指出所有构造函数都被视为特殊成员函数,这似乎与标准相矛盾。
太棒了;
构造函数是使用函数声明符声明的,因此它是一个函数,因此也是一个成员函数。
class.mem指出:
类定义中的成员规范声明了该类的完整成员集;不能在其他地方添加任何成员。类 X 的直接成员是首先在 X 的成员规范中声明的 X 成员,包括匿名联合成员 ([class.union.anon]) 及其直接成员。 类的成员包括数据成员、成员函数([class.mfct])、嵌套类型、枚举器和成员模板 ([temp.mem]) 及其特化。
现在我们转到class.mem#general-3来看看什么是成员函数:
数据成员是由成员声明符引入的非函数成员。成员函数是作为函数的成员。 嵌套类型是在类中声明的类([class.name]、[class.nest])和枚举([dcl.enum])以及使用 typedef 声明([dcl.typedef])声明为成员的任意类型或别名声明。类中定义的无作用域枚举的枚举器是该类的成员。
现在我们需要证明 ctor 是一个函数,因此我们转向class.ctor.general#1:
如果声明器是以下形式的函数声明器 ([dcl.fct]),则声明器声明构造函数
Run Code Online (Sandbox Code Playgroud)ptr-declarator ( parameter-declaration-clause ) noexcept-specifieropt attribute-specifier-seqopt其中 ptr 声明符仅由 id-表达式、可选的属性说明符-seq 和可选的括号组成,并且 id-表达式具有以下形式之一:
- 在友元声明 ([class.friend]) 中,id-表达式是命名构造函数 ([class.qual]) 的限定 ID;
- 否则,在属于类或类模板的成员规范的成员声明中,id-表达式是直接封闭实体的注入类名 ([class.pre]);
需要注意的重要一点是,构造函数是使用声明器声明的,该声明器是函数声明器。现在要看到ctor 的函数声明符声明了一个函数,我们将其移至dcl.spec.auto.general:
占位符类型可以与函数声明符一起出现在 decl-specifier-seq、type-specifier-seq、conversion-function-id 或 Trailing-return-type 中,在此类声明符有效的任何上下文中。 如果函数声明符包含尾随返回类型 ([dcl.fct]),则该尾随返回类型指定函数的声明返回类型。否则,函数声明符应声明一个函数。 如果函数声明的返回类型包含占位符类型,则函数的返回类型将从函数体 ([stmt.if]) 中的未丢弃的 return 语句(如果有)推导出来。
现在,由于 ctor 的函数声明符形式不包含尾随返回类型,因此 ctor 的函数声明符根据上述引用声明一个函数。
由此证明, ctor S::S(int, float, double) 是一个函数,因此是一个成员函数。
dcl.constexpr中还支持构造函数是函数的声明:
如果满足以下条件,则函数适合 constexpr:
- 如果该函数是构造函数或析构函数,则其类没有任何虚拟基类。
这也表明构造函数是一个函数。
构造函数,即不是特殊的成员函数,仍然是成员函数吗?
是的,因为构造函数S::S(int, float, double)是在类的 成员规范S内声明的,所以根据定义,该声明是成员函数声明。
基本上,类的成员规范内的声明是成员声明。如果声明是
所以是的,S::S(int, float, double)是一个成员函数。
| 归档时间: |
|
| 查看次数: |
349 次 |
| 最近记录: |