继承构造函数

时间:2016-01-08 07:43:43

标签: c++ c++11 name-lookup inheriting-constructors injected-class-name

请考虑以下代码:

struct base {};

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

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

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

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

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

  

成员名称查找确定类范围中名称( id-expression )的含义。 [...]对于 id-expression ,名称查找从this的类范围开始

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

  

[类范围] f中[成员名称] C的名称查找结果是 S(f,C)的声明集

我尝试按C derived f basebase foo()使用p3来执行此程序。

"宣言集"在f

中定义
  

Cf查找集,名为 S(f,C),由两个组件集组成:声明集,一组名为p4的成员; [...]

C告诉我们声明集的内容:

  

如果f包含名称f的声明,则声明集包含C中声明的using base::base声明,满足语言结构的要求。查找发生。

basefderived)中名称Cusing base::base)的声明。该段继续举例说明声明对于满足查找发生的语言结构要求的含义,但没有任何内容可以排除{{1从这次查找。

接下来,在p3向下,我们会告诉我们如何处理声明集中的 using-declarations

  

在声明集中, using-declarations 被替换为未被派生类成员隐藏或覆盖的指定成员集

那么成员using base::base指定的是什么?在[class.qual] p2

回答我的回答
  

在查找中,不忽略函数名称和    nested-name-specifier 指定一个类C

     
      
  • 如果在C中查找 nested-name-specifier 之后指定的名称,则为C的注入类名称,或者

  •   
  • using-declaration member-declaration 中,如果在 nested-name-specifier 之后指定的名称是相同的   嵌套名称说明符

  • 的最后一个组件中的标识符 [...]   
     

而是将名称视为命名类C的构造函数。

有一个脚注,阐明了哪些"查找哪些函数名称不被忽略"的意思是:

  

忽略函数名称的查找包括出现在嵌套名称说明符中的名称, elaborated-type-specifier base-specifier

这些名称查找的情况都不是这样,所以在我看来这个段落适用,并说using base::base指定构造函数(这也是你直觉所期望的,鉴于它是继承构造函数声明。)

在派生类范围内找到声明(指定基类构造函数)之后,我们继续关注[class.member.lookup] p4

  

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

也就是说,由于名称查找在派生类范围内找到了结果,因此它不会继续查找基类范围(它会找到 inject-class-name {{1 }})。 [顺便说一句,即使名称查找继续进入基类范围,我也看不到任何会在构造函数和注入类名称之间消除歧义的东西。

我的推理在哪里出错?

1 个答案:

答案 0 :(得分:4)

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

C ++11§12.1/ 1
  

构造函数没有名称。

C +11§12.1/ 2
  

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