简体   繁体   English

合格基类的名称查找

[英]Name lookup of qualified base class

Consider this code: 考虑以下代码:

#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(); }

Output from g++ is: 来自g ++的输出是:

D::S
D::S

My questions are: 我的问题是:

  • How does (1) work - I would have though that the name of the base class is D::S specifically (1)的工作方式-虽然我将基类的名称专门指定为D::S
  • Are (1) and (2) both required to work? (1)和(2)都需要工作吗?
  • Why does S s; 为什么S s; inside f() refer to D::S and not ::S ? f()内部引用D::S而不是::S

Within the body of the class D::S the name S refers to itself, obviously. 显然,在类D::S的内部,名称S指向其自身。 This is called the "injected class name". 这称为“注入的类名”。 You can think of it as though there is a public member typedef in D::S with its own name, S . 您可以认为它好像D::S有一个公共成员typedef,其名称为S

  • How does (1) work - I would have though that the name of the base class is D::S specifically (1)的工作方式-虽然我将基类的名称专门指定为D :: S

X derives from D::S , because you said so in the base class list of X . X源自D::S ,因为您在X的基类列表中是这样说的。

A derived class has access to the names declared in a base class, so name lookup in X first looks at its own members and its base class' members, then looks for names in the enclosing scope outside X . 派生类可以访问在基类中声明的名称,因此X名称查找首先查看其自身的成员及其基类的成员,然后在X之外的封闭范围内查找名称。 Because the injected class name S is a member of D::S , it gets found in X , that's why (1) works. 由于注入的类名SD::S的成员,因此可以在X找到它,这就是(1)起作用的原因。 The type ::S is not found because name lookup finds the injected class name and never looks in the enclosing scope (if it did find ::S the code wouldn't compile, because ::S is not a base class of X ). 该类型::S没有找到,因为名称查找发现注入的类名和从不看在封闭范围(如果它没有找到::S的代码将无法编译,因为::S不是一个基类的X ) 。

As an analogy consider this example using a member typedef declared in D::S : 作为类推,考虑使用D::S声明的成员typedef的示例:

namespace D {
  struct S {
    struct S { S(){std::cout << "D::S\n";} };
    typedef S AnotherName;
  };
}

struct X : D::S {
  X() : AnotherName() { }
};

This works because the name AnotherName is found in the base class, and is a synonym for the type of the base class, D::S . 之所以AnotherName是因为在基类中找到了名称AnotherName ,并且该名称是基类D::S的同义词。 The injected class name works similarly, except that the name that gets injected is the class' own name, S , not some other name like AnotherName . 注入的类名的工作方式类似,不同之处在于,注入的类名是该类自己的名称S ,而不是其他名称,例如AnotherName

  • Are (1) and (2) both required to work? (1)和(2)都需要工作吗?

Yes. 是。

(2) works because D::S is the fully-qualified named of S so it refers to the same type, but using its "full name" that non-members must use to refer to the type. (2)的作品,因为D::S是完全合格的命名的S所以它指的是同一类型,但使用它的“全名”非成员必须使用引用类型。

  • Why does S s; 为什么S s; inside f() refer to D::S and not ::S ? 在f()内部引用D :: S而不是:: S?

Because like the constructor, f() is a member of X so name lookup looks inside the scope of X (and its base classes) first, and so finds the injected class name. 因为像构造函数一样, f()X的成员,所以名称查找首先在X (及其基类)的范围内进行,然后查找注入的类名称。 It never see the type ::S at global scope because it finds the name S as a member of the base class and stops looking. 它永远不会在全局范围内看到类型::S ,因为它会找到名称S作为基类的成员并停止查找。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM