为什么C++中构造函数/析构函数不能使用别名?

3

参加这个课程:

class Foo {
public:
   using MyType = Foo;

   MyType* m = nullptr; //ok

   MyType* functor() { //ok
      return nullptr;
   }

   MyType() = default; //error
   ~MyType() = default; //error
};

为什么可以为成员使用别名,但不能为构造函数或析构函数使用别名?

请参考如何提问,其中第一步是“搜索和研究”,您会发现许多相关的SO帖子。 - Jason
2个回答

5

由于这被标记为language-lawyer,让我们看看标准的规定。

[class.ctor.gen]中,强调如下:

如果声明符是函数声明符([dcl.fct]),形式为ptr-declarator(parameter-declaration-clause)noexcept-specifieropt attribute-specifier-seqopt,则该声明符声明了一个构造函数,其中ptr-declarator仅由id-expression、可选的attribute-specifier-seq和可选的括号组成,且id-expression具有以下形式之一:

(1.1) 在友元声明([class.friend])中,id-expression是一个限定的id,它命名了一个构造函数([class.qual]);
(1.2) 否则,在属于类或类模板的成员说明的成员声明中,id-expression是最近封闭实体的注入类名([class.pre]);
(1.3) 否则,id-expression是一个限定-id,其未限定-id是其查找上下文的注入类名。

对于为什么名称别名不适用于声明构造函数,特别是(1.2)的相关性,这里需要进行阐述。它指出id-expression是injected-class-name[..]。后者在[class.pre]中定义:
  1. 类是一种类型。其名称在其范围内成为类名([class.name])。
    [..]
  2. 类名也绑定在类(模板)本身的作用域中;这被称为注入类名。 为了进行访问检查,注入类名被视为公共成员名称。[..]
这非常明确地说明,注入类名恰好是用于首次声明类的名称。在措辞中没有别名的容忍余地。
这遵循了类模板中所见的相同机制:
template <typename T> class C { C foo(); };

现在,没有名为C的类,C是一个模板,因此您通常希望使用C<T> foo();。但是如[class.pre]中所述,在类定义的作用域中引入了一个class-name,该名称指向实际类型。因此,即使没有任何类Cclass-name C也可以用作C<T>的简写,在构造函数和析构函数的情况下,这是唯一的引用方式,因为它们的声明不允许使用任何类型标识符,但class-name只能使用。

3

m是指向别名类型实例的指针。没问题。

functor()返回指向别名类型实例的指针。没问题。

但是构造函数/析构函数本身不是类型,因此您不能为它们使用类型别名。它们必须以所属类型命名。这只是语法工作的方式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接