[英]Name lookup of qualified base class
考虑以下代码:
#include <iostream>
namespace D
{
struct S { S(){std::cout << "D::S\n";} };
}
struct S { S(){std::cout << "S\n";} };
struct X: D::S
{
X(): S() {} // (1)
// X(): D::S() {} // (2)
void f() { S s; }
};
int main() { X x; x.f(); }
来自g ++的输出是:
D::S
D::S
我的问题是:
D::S
S s;
在f()
内部引用D::S
而不是::S
? 显然,在类D::S
的内部,名称S
指向其自身。 这称为“注入的类名”。 您可以认为它好像D::S
有一个公共成员typedef,其名称为S
- (1)的工作方式-虽然我将基类的名称专门指定为D :: S
X
源自D::S
,因为您在X
的基类列表中是这样说的。
派生类可以访问在基类中声明的名称,因此X
名称查找首先查看其自身的成员及其基类的成员,然后在X
之外的封闭范围内查找名称。 由于注入的类名S
是D::S
的成员,因此可以在X
找到它,这就是(1)起作用的原因。 该类型::S
没有找到,因为名称查找发现注入的类名和从不看在封闭范围(如果它没有找到::S
的代码将无法编译,因为::S
不是一个基类的X
) 。
作为类推,考虑使用D::S
声明的成员typedef的示例:
namespace D {
struct S {
struct S { S(){std::cout << "D::S\n";} };
typedef S AnotherName;
};
}
struct X : D::S {
X() : AnotherName() { }
};
之所以AnotherName
是因为在基类中找到了名称AnotherName
,并且该名称是基类D::S
的同义词。 注入的类名的工作方式类似,不同之处在于,注入的类名是该类自己的名称S
,而不是其他名称,例如AnotherName
。
- (1)和(2)都需要工作吗?
是。
(2)的作品,因为D::S
是完全合格的命名的S
所以它指的是同一类型,但使用它的“全名”非成员必须使用引用类型。
- 为什么S s; 在f()内部引用D :: S而不是:: S?
因为像构造函数一样, f()
是X
的成员,所以名称查找首先在X
(及其基类)的范围内进行,然后查找注入的类名称。 它永远不会在全局范围内看到类型::S
,因为它会找到名称S
作为基类的成员并停止查找。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.