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

时间:2015-06-04 20:06:44

标签: 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); }
    };
}

当用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; }
                                       ^

在错误中注意它引用T = A::Foo,即使在调用站点我在命名空间Foo内创建B。如果我删除基类decl(: A::Foo),那么所有编译都很好。

这似乎表明继承自A::Foo以某种方式将其带入我的命名空间并将其与我对Foo的使用相匹配?什么是C ++&#34;功能&#34;导致这个?

(当然,这个问题很容易通过命名空间使用Foo来修复,但这不是问题。)

2 个答案:

答案 0 :(得分:5)

由于注入了类名称规则,类的名称就像是成员一样可见。

9/2

  

class-name 被插入到在看到 class-name 之后立即声明它的范围内。 class-name 也会插入到类本身的范围内;这被称为 inject-class-name 。出于访问检查的目的,inject-class-name被视为公共成员名称。

因此,类A::Foo包含一个名为Foo类型的成员A::Foo。由于Bar::Blah()中的名称查找在命名空间成员之前考虑Bar的基本成员,因此Foo的名称查找会找到注入的类名,其名称为A::Foo

答案 1 :(得分:3)

  

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

排序。如果在类中查找名称失败,则在基类中继续查找。

  

10.2会员名称查询

     

...

     

5否则(即C不包含f的声明或结果声明集为空), S(f,C) 最初为空。如果C具有基类,则在每个直接基类子对象f中计算Bi的查找集,并合并每个此类查找集 S(f,Bi) 反过来进入 S(f,C)

会员名称查找也包括查找嵌套类型。在同一部分的后面,我们发现:

  

9 [注意:即使对象具有多个类型为T的基类子对象,也可以明确地找到基类T中定义的静态成员,嵌套类型或枚举器。基类子对象共享其公共虚拟基类的非静态成员子对象。 -end note ]