在继承构造函数后查找基类名称

Lookup of base class name after inheriting constructor

本文关键字:基类 查找 继承 构造函数      更新时间:2023-10-16

考虑以下代码:

struct base {};
struct derived : public base {
    using base::base;
    base foo() const;  // how does name lookup on 'base' here work?
};

直观地说,很明显,这段代码是有效的,而且它确实可以编译(用gcc和clang测试)。

然而,我想了解标准中的哪些内容使其有效。具体来说,我想了解base foo()base的名称查找是如何找到基类类型而不是继承的构造函数的。

以下是我对标准措辞的分析,表明它应该解析为构造函数。这可能是错误的,但我想知道我哪里错了。

我从[class.member.lookup] p1:开始

成员名称查找确定类作用域中名称(id表达式)的含义。[…]对于id表达式,名称查找从this 的类范围开始

p7告诉我们名称查找的结果是什么:

在[a类作用域]C中查找[a成员名称]f的名称的结果是S(f,C)的声明集

我试图遵循这个过程,Cderivedfbase foo()base的使用。

p3:中定义了"声明集"

Cf查找集称为S(f,C),由两个组件集组成:声明集

p4告诉我们进入声明集的内容:

如果C包含名称为f的声明,则声明集包含在C中声明的f的每个声明,这些声明满足发生查找的语言构造的要求。

using base::basederivedC)中的名称basef)的声明。该段接着举例说明了而非声明满足查找所在的语言结构的要求意味着什么,但没有什么可以将using base::base排除在该查找之外。

接下来,在p3中,我们将了解如何处理在声明集中使用声明

在声明集中,使用声明被指定成员的集合所替换,这些指定成员未被派生类的成员隐藏或覆盖

那么using base::base指定了哪些成员?在我看来,这是由[class.qual] p2:回答的

在函数名不被忽略并且嵌套名称说明符命名类C:

  • 如果在C中查找时,在嵌套名称说明符之后指定的名称是C或的注入类名

  • 在作为成员声明的using声明中,如果在嵌套名称说明符之后指定的名称与嵌套名称说明符的最后一个组件中的标识符[…]

该名称被认为是对类CCD_ 34的构造函数进行命名。

有一个脚注阐明了"函数名称不被忽略的查找"的含义:

忽略函数名称的查找包括出现在嵌套名称说明符详细类型说明符说明符中的名称。

这些都不是所讨论的名称查找的情况,所以在我看来,这段话适用,并说using base::base指定构造函数(这也是你直观地期望的,因为它是继承构造函数声明)。

在派生类作用域中找到一个声明(指定基类构造函数)后,我们继续执行[class.member.lookup] p4:

如果生成的声明集不为空,则子对象集包含C本身,并且计算完成。

也就是说,由于名称查找在派生类作用域中找到了一个结果,因此它不会继续在基类作用域中查找(它将在其中找到注入的类名base)。[顺便说一句,即使名称查找继续到基类范围,我也看不到任何东西会消除构造函数和注入的类名]之间的歧义。

我的推理哪里出了问题?

标准煞费苦心地指出构造函数没有名称。无法通过名称查找找到它,因为它没有名称。

C++11§12.1/1

"构造函数没有名称。

C+11§12.1/2

"因为构造函数没有名称,所以它们是在名称查找过程中从未找到。