C++:从类继承是否会将其带入命名空间?

Aar*_*pel 7 c++ namespaces

这是一些人为的示例代码:

template<typename T> void Do(T arg) { (void)arg->b; }

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

namespace B {
    struct Foo { int b; };
    struct Bar : A::Foo {
        void Blah() { Do((Foo *)0); }
    };
}
Run Code Online (Sandbox Code Playgroud)

哪个用gcc 4.8.2编译时(clang给出了类似的错误):

namespacebug.cpp: In instantiation of ‘void Do(T) [with T = A::Foo*]’:
namespacebug.cpp:10:34:   required from here
namespacebug.cpp:1:39: error: ‘struct A::Foo’ has no member named ‘b’
 template<typename T> void Do(T arg) { (void)arg->b; }
                                       ^
Run Code Online (Sandbox Code Playgroud)

请注意,它引用的错误T = A::Foo即使在调用站点我正在创建一个Foo内部命名空间B.如果我删除基类decl(: A::Foo)然后所有编译都很好.

这似乎表明从A::Foo某种方式继承将其带入我的命名空间并将其与我的使用相匹配Foo?什么C++"功能"导致了这个?

(当然,这个问题可以通过命名空间我的使用轻松解决Foo,但这不是问题.)

asc*_*ler 5

由于inject-class-name规则,类的名称可见,就像它是成员一样.

9/2

一个类名被插入在其中后立即宣布的范围类的名字能够被看见.的类名也被插入到类本身的范围; 这被称为注入类名.出于访问检查的目的,inject-class-name被视为公共成员名称.

因此,类似于A::Foo包含一个Foo命名该类型的成员A::Foo.由于名称查找Bar::Blah()考虑了Bar之前名称空间成员的基本成员,因此名称查找用于Foo查找注入的类名称,即名称A::Foo.