我最近发现使用using
将基类函数导入到派生类的名称空间中(当它被隐藏时)。我试图用它从基类导入一个函数作为派生类中函数的实现:
class A {
public:
virtual void foo() = 0;
};
class B {
public:
void foo() {
}
};
class C : public A, public B {
public:
using B::foo;
};
int main()
{
C c;
}
这不会编译,因为A::foo()
是C
中的纯虚函数。我希望using B::foo;
能够实现foo()
。为什么不是这样呢?
答案 0 :(得分:4)
您有两个不同的功能:A::foo()
和B::foo()
。虽然它们具有相同的非限定名称,但它们不相关。 B::foo()
没有也无法覆盖A::foo()
,因为B
不是A
的子类。
C
继承了A
和B
的两个功能。您对两个基类都使用公共继承,因此在A::foo()
中B::foo()
和C
已经可见(请注意,您需要限定名称来调用函数以避免歧义)。
所以你的使用声明实际上没有效果。
使用声明在类中使用时,与 overloading 有关,但它与 overriding 无关。这些非常不同的概念。
重载是关于具有相同名称但不同参数集的不同函数。
覆盖是关于多态的,即在派生类中具有不同的基类方法实现。
using声明将基类中的函数名称引入派生类,其中该名称将被另一个具有相同名称但不同参数的函数隐藏。例如:
class X
{
public:
void func() {}
};
class Y : public X
{
public:
void func(int arg) {}
};
Y::func
不会覆盖 X::func
,因为它的参数不同。此外,它还隐藏基类中的名称func
,因此只能通过限定名称来调用它,例如:
X x;
x.func(); // ok
Y y;
y.func(1); // ok, Y::func called
y.func(); // error, base-class name func is hidden by local name
y.X::func(); // ok, qualified name, X::func called
在这种情况下,using声明会将基类中的名称引入派生类,使得func
可以在没有名称限定的情况下调用:
class Y : public X
{
public:
using X::func;
void func(int arg) {}
};
// ...
Y y;
y.func(); // ok, X::func called
答案 1 :(得分:0)
using
具有不同的含义,并指定您希望能够访问另一个命名空间中的函数/对象,而无需显式键入命名空间名称。它与覆盖无关。