C++的类是名字空间吗?显然不是。但C++的类某种意义上又是名字空间,因为对名字空间可以做的操作都能够在同样意义上应用在类上,除非某个操作是类明确禁止的。这一段是摘自《D&R》。
这也意味着对于基类和子类,两个是不同的名字空间。而且可以理解成子类是嵌套在基类的名字空间内的。这样如果子类的成员将遮蔽基类具有同样名字的成员。这就是说基类的名字被子类隐藏了。这样在外面如果要通过子类对象引用基类被隐藏的名字就需要显式地用域作用符来指定。
比如下面这样:
class Base
{
public:
void f(){cout<<"Base f()/r/n";};
};
class Derive : public Base
{
public:
void f(){cout<<"Derive f()/r/n";};//Hidden Base::f()
};
int main()
{
Derive d;
d.Base::f();//calls Base::f()
d.f();//calls Derive::f()
}
如果把Base::f引入进Derive呢?
class Derive : public Base
{
public:
using Base::f;
void f(){cout<<"Derive f()/r/n";};
};
结果仍然和之前一样:
int main()
{
Derive d;
d.Base::f();//calls Base::f()
d.f();//calls Derive::f()
}
注意到两个f()的原型是一样的,而这并没有被阻止,但是对于名字空间则有些不同:
namespace NS_A
{
void f(int){cout<<"NS_A:f(int)/r/n";};
}
namespace NS_B
{
using NS_A::f;
void f(int){cout<<"NS_B:f(int)/r/n";};//error: 'void NS_B::f(int)' conflicts with previous using declaration 'void
NS_A::f(int)'
}
为什么是这样呢?我想可能是因为类对象调用时是有类型的,而namespace并不是类型。所以当用Derive d.f()时编译器可以知道要的是Derive的f。但是如果同时using NS_B然后调用f时应该调用哪个呢?
再看另外一种情况:
class Base
{
public:
void f(){cout<<"Base f()/r/n";};
void f(int){cout<<"Base f(int)/r/n";};
};
class Derive : public Base
{
public:
void f(){cout<<"Derive f()/r/n";};
};
int main()
{
Derive d;
d.Base::f();
//d.f(2);//error: no matching function for call to 'Derive::f(int)'
}
因为derive的f把Base的f隐藏了。也就是说是按名字而不是原型来隐藏。
所以如果要想调用基类f(int)就需要using进子类:
class Base
{
public:
void f(){cout<<"Base f()/r/n";};
void f(int){cout<<"Base f(int)/r/n";};
};
class Derive : public Base
{
public:
using Base::f;
void f(){cout<<"Derive f()/r/n";};
};
int main()
{
Derive d;
d.Base::f();
d.f(2);
}
类似的如果是私有继承也需要using进来
class Base
{
public:
void f(){cout<<"Base f()/r/n";};
void f(int){cout<<"Base f(int)/r/n";};
};
class Derive : private Base
{
public:
void f(){cout<<"Derive f()/r/n";};
};
int main()
{
Derive d;
d.f(2);//error: no matching function for call to 'Derive::f(int)'
}
class Base
{
public:
void f(){cout<<"Base f()/r/n";};
void f(int){cout<<"Base f(int)/r/n";};
};
class Derive : private Base
{
public:
using Base::f;
void f(){cout<<"Derive f()/r/n";};
};
int main()
{
Derive d;
d.f(2);// ok, calls Base::f(int)
}