显然,在类的主体中,D::S
名称S
指的是自身。这称为“注入的类名”。你可以把它想象成有一个公共成员 typedef ,D::S
它有自己的名字,S
.
- (1) 是如何工作的 - 我会认为基类的名称是 D::S
X
派生自D::S
,因为您在 的基类列表中这么说X
。
派生类可以访问基类中声明的名称,因此名称查找X
首先查看它自己的成员及其基类的成员,然后在外部的封闭范围内查找名称X
。因为注入的类名S
是 的成员D::S
,所以可以在 中找到X
,这就是 (1) 起作用的原因。::S
找不到类型,因为名称查找找到了注入的类名称,并且从不在封闭范围内查找(如果确实找到::S
代码将无法编译,因为::S
它不是 的基类X
)。
作为一个类比,考虑使用在中声明的成员 typedef 的示例D::S
:
namespace D {
struct S {
struct S { S(){std::cout << "D::S\n";} };
typedef S AnotherName;
};
}
struct X : D::S {
X() : AnotherName() { }
};
这是有效的,因为该名称AnotherName
是在基类中找到的,并且是基类类型的同义词,D::S
. 注入的类名的工作方式类似,只是注入的名称是类自己的名称,S
而不是其他名称,例如AnotherName
.
是的。
(2) 之所以有效,是因为D::S
它是完全限定的命名,S
所以它引用相同的类型,但使用非成员必须使用的“全名”来引用该类型。
- 为什么 S s; 在 f() 中指的是 D::S 而不是 ::S ?
因为和构造函数一样,f()
是so name lookup 的成员,首先在(及其基类)X
的范围内查找,从而找到注入的类名。它永远不会在全局范围内X
看到该类型,因为它发现该名称是基类的成员并停止查找。::S
S