为什么有一个注入的类名?

最近,我看到了一个奇怪的 C + + 特性: 注入的类名

class X { };
X x1;
class X::X x2; // class X::X is equal to X
class X::X::X x3; // ...and so on...

但是我不明白为什么这个特性是必需的。有什么实践需要这个特性吗?

我听说这个特性在旧的 C + + 中并不存在。那么,它是什么时候被引入的呢? C + + 03? C + + 11?

7918 次浏览

注入的类名意味着 X被声明为 X的一个成员,因此 X内部的名称查找总是找到当前的类,而不是另一个可能在同一封闭范围内声明的 X,例如。

void X() { }
class X {
public:
static X create() { return X(); }
};

create()函数是创建一个临时 X对象还是调用函数 X?在名称空间范围内,它将调用函数,因此注入的 class-name 的目的是确保在 X的主体中,名称始终能够找到类本身(因为在查找封闭范围之前,名称查找将在类自身的范围内启动)。

它在类模板中也很有用,注入的类名可以在没有模板参数列表的情况下使用,例如使用简单的 Foo而不是完整的模板 id Foo<blah, blah, blah>,所以很容易引用当前的实例化。有关 C + + 98和 C + + 03之间的更改,请参见 DR 176

注入类名的想法出现在 C + + 98中,但是这个术语对于 C + + 03来说是新的。

C + + 98表示:

在看到 类别名称之后,立即将 类别名称插入到声明它的作用域中。类名也被插入到类本身的作用域中。

第二个句子被 DR 147修改了,所以 C + + 03在[ class ]/2中说:

在看到 类别名称之后,立即将 类别名称插入到声明它的作用域中。类别名称也被插入到类本身的作用域中; 这就是所谓的 注入类名

甚至在 C + + 98之前,ARM 就有大致相同的措辞,这意味着类的名字总是可以在类主体中用来引用类本身:

即使在类说明符本身的 成员名单中,类的名称也可以用作 类别名称

  • 比如说,

    class link { link* next; };