Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;:从类继承是否会将其引入命名空间?_C++_Namespaces - Fatal编程技术网

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