C++ C++;:从类继承是否会将其引入命名空间?
下面是一些人为设计的示例代码:C++ C++;:从类继承是否会将其引入命名空间?,c++,namespaces,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); } }; } template vo
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); }
};
}
template void Do(T arg){(void)arg->b;}
名称空间A{
结构Foo{int a;};
}
命名空间B{
结构Foo{intb;};
结构栏:A::Foo{
void Blah(){Do((Foo*)0);}
};
}
当使用gcc 4.8.2进行编译时(clang给出了类似的错误):
namespacebug.cpp:voiddo(T)[with T=A::Foo*]的实例化中:
namespacebug.cpp:10:34:此处为必填项
namespacebug.cpp:1:39:错误:“结构A::Foo”没有名为“b”的成员
模板void Do(T arg){(void)arg->b;}
^
请注意,在错误中,它引用了T=A::Foo
,即使在调用站点,我正在命名空间B
中创建Foo
。如果我删除基类decl(:A::Foo
),那么所有的编译都很好
这似乎表明从A::Foo
继承会以某种方式将其引入我的命名空间,并将其与我对Foo
的使用相匹配?C++的“特征”是什么引起的?
(当然,这个问题可以通过我使用Foo
的名称空间轻松解决,但这不是问题所在。)
从类继承是否会将其引入命名空间
有点。如果在类中查找名称失败,则在基类中继续查找
10.2成员名称查找
5否则(即,C
不包含f
的声明或生成的声明集为空),S(f,C)
最初为空。如果C
有基类,则计算每个直接基类子对象Bi
中f
的查找集,并将每个这样的查找集S(f,Bi)
依次合并为S(f,C)
成员名称查找也包括嵌套类型的查找。在同一节的后面,我们发现:
9[注:即使一个对象有多个类型为T的基类子对象,也可以明确地找到基类T中定义的静态成员、嵌套类型或枚举数。两个基类子对象共享其公共虚拟基类的非静态成员子对象。-结束注]
由于注入的类名规则,类的名称是可见的,就像它是一个成员一样 9/2 在看到类名后立即将类名插入到声明它的范围中。类名也被插入到类本身的作用域中;这称为注入的类名。出于访问检查的目的,注入的类名被视为公共成员名
因此,类
A::Foo
包含一个成员Foo
,该成员将类型命名为A::Foo
。由于Bar::Blah()
中的名称查找在命名空间成员之前考虑Bar
的基本成员,因此Foo
的名称查找将查找注入的类名,该类名命名为A::Foo
(void)arg->b代码>-这是什么意思?@EdHeal,我想这只是为了迫使error@StoryTeller-那么做愚蠢的事情有什么意义呢?@EdHeal,这一点是为了证明在不同的场景中名称查找会返回不同的结果。@EdHeal,虽然我同意这样做应该指导开发人员进行更好的设计,这个问题是关于语言机制的。举个例子就可以了。它将帮助未来希望了解该功能的SO用户。和其他好书中糟糕的代码一样,这有助于学习。这是为会员准备的。这是一个类型,不是成员,它与基类类型相匹配。@Aardappel Correct。但是,注入的类名是基类的成员,与其他成员一样被继承。这就是如何编写类似struct A{};结构B:A{};int main(){B::A();}
@Aardappel,名称查找也包括嵌套类型。看我的更新。我想你是对的。但很奇怪,因为它几乎违反了名称空间规则。
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; }
^