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

C++: Does inheriting from a class bring it into the namespace?

本文关键字:命名空间 是否 继承 c++      更新时间:2023-10-16

下面是一些做作的示例代码:

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,即使在调用站点,我在命名空间B中创建了Foo。如果我删除基类decl (: A::Foo),那么所有编译都很好。

这似乎表明继承A::Foo以某种方式将其带入我的命名空间并将其与我使用的Foo相匹配?是什么c++"特性"导致了这种情况?

(当然,这个问题可以很容易地通过命名空间我使用Foo来解决,但这不是问题。)

由于使用了inject -class-name规则,类名就像成员一样可见。

9/2

类名出现后,立即将类名插入声明它的作用域。类名也被插入到类本身的作用域中;这就是所谓的注入类名。出于访问检查的目的,注入的类名被视为公共成员名。

因此,好像类A::Foo包含一个成员Foo,该成员将类型命名为A::Foo。由于Bar::Blah()中的名称查找在名称空间成员之前考虑Bar的基本成员,因此Foo的名称查找查找注入的class-name,它命名A::Foo

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

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

10.2查找成员名

5否则(即C不包含f的声明或结果声明集为空), S(f,C) 初始为空。如果C有基类,计算f在每个直接基类子对象Bi中的查找集,并依次将每个查找集 S(f,Bi) 合并为 S(f,C)

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

9 [注:可以明确地找到基类T中定义的静态成员、嵌套类型或枚举数,即使对象具有多个T类型的基类子对象。两个基类子对象共享它们共同虚基类的非静态成员子对象。 -end note]