复制构造函数中的C ++名称空间冲突

Vin*_*our 25 c++ inheritance namespaces language-lawyer

我有以下代码:

namespace A {
    struct Foo {
        int a;
    };
}

struct Foo {
    int b;
};

struct Bar : public A::Foo {
    Bar(Foo foo) {
        c = foo.b;
    }
    int c;
};
Run Code Online (Sandbox Code Playgroud)

C ++编译器抱怨“ c = foo.b”,因为A :: Foo没有名为b的成员。如果我用:: Foo更改Bar参数的类型,它将起作用。

我的问题是此行为背后的原因是什么(我想这与继承使Bar进入A名称空间这一事实有关,但是我找不到任何文档来支持该理论。

Sto*_*ica 18

每个类均以其成员的名义注入其名称。所以你可以命名A::Foo::Foo。这称为注入的类名。

[类]

2在看到类名之后,立即将一个类名插入到声明该类名的范围中。类名也被插入到类本身的作用域中。这称为注入类名称。为了进行访问检查,将注入的类名视为公共成员名。

[basic.lookup]

3为了隐藏和查找名称,一个类的注入的类名也被认为是该类的成员。

因为参数类型的不合格名称查找始于该类的范围Bar,所以它将继续进入其基类的范围以说明那里的任何成员。它将找到A::Foo::Foo一个类型名称。

如果要使用全局类型名称,只需通过其周围的(全局)名称空间对其进行限定。

Bar(::Foo foo) {
    c = foo.b;
}
Run Code Online (Sandbox Code Playgroud)

这将在未出现注入的类名的范围内进行完全限定的查找。

有关后续“为什么”的问题,请参见

  • @TedLyngmo-ADL与函数调用一起发生,与这些特定段落无关。 (5认同)
  • 这导致了非常有趣的`struct Bar :: A :: Foo :: Foo :: Foo :: Foo :: Foo {};`但[有上下文](http://eel.is/c++draft /basic.lookup.qual#class.qual-2),其中`A :: Foo :: Foo`指定构造函数,因此您无法继续添加任意数量的`Foo`。这类似于(但机制完全不同),您可以通过以下方式调用函数f:(************ f)()。 (3认同)