什么是函数隐藏?
...是一种名称隐藏的形式。一个简单的例子:
void foo(int);
namespace X
{
void foo();
void bar()
{
foo(42); // will not find `::foo`
// because `X::foo` hides it
}
}
这也适用于基类中的名称查找:
class Base
{
public:
void foo(int);
};
class Derived : public Base
{
public:
void foo();
void bar()
{
foo(42); // will not find `Base::foo`
// because `Derived::foo` hides it
}
};
什么是函数覆盖?
这与虚函数的概念有关。[class.virtual]/2
如果在一个类和一个类vf
中声明了一个虚成员函数,直接或间接地派生自一个与被声明,然后也是虚拟的(无论它是否被声明)并且它覆盖.Base
Derived
Base
vf
Base::vf
Derived::vf
Base::vf
class Base
{
private:
virtual void vf(int) const &&;
virtual void vf2(int);
virtual Base* vf3(int);
};
class Derived : public Base
{
public: // accessibility doesn't matter!
void vf(int) const &&; // overrides `Base::vf(int) const &&`
void vf2(/*int*/); // does NOT override `Base::vf2`
Derived* vf3(int); // DOES override `Base::vf3` (covariant return type)
};
调用虚函数时,最终的覆盖器变得相关:[class.virtual]/2
C::vf
类对象的虚成员函数S
是最终覆盖器,除非其最派生类S
是基类子对象(如果有)声明或继承了另一个覆盖的成员函数vf
。
即,如果您有一个类型为 的对象S
,则最终覆盖器是您在遍历类层次结构S
返回其基类时看到的第一个覆盖器。重要的一点是函数调用表达式的动态类型用于确定最终的覆盖器:
Base* p = new Derived;
p -> vf(42); // dynamic type of `*p` is `Derived`
Base& b = *p;
b . vf(42); // dynamic type of `b` is `Derived`
覆盖和隐藏有什么区别?
本质上,基类中的函数总是被派生类中的同名函数隐藏;无论派生类中的函数是否覆盖基类的虚函数:
class Base
{
private:
virtual void vf(int);
virtual void vf2(int);
};
class Derived : public Base
{
public:
void vf(); // doesn't override, but hides `Base::vf(int)`
void vf2(int); // overrides and hides `Base::vf2(int)`
};
要查找函数名称,使用表达式的静态类型:
Derived d;
d.vf(42); // `vf` is found as `Derived::vf()`, this call is ill-formed
// (too many arguments)
它们与函数重载有什么关系?
由于“函数隐藏”是名称隐藏的一种形式,如果函数名称被隐藏,所有重载都会受到影响:
class Base
{
private:
virtual void vf(int);
virtual void vf(double);
};
class Derived : public Base
{
public:
void vf(); // hides `Base::vf(int)` and `Base::vf(double)`
};
For function overriding, only the function in the base class with the same arguments will be overriden; you can of course overload a virtual function:
class Base
{
private:
virtual void vf(int);
virtual void vf(double);
void vf(char); // will be hidden by overrides in a derived class
};
class Derived : public Base
{
public:
void vf(int); // overrides `Base::vf(int)`
void vf(double); // overrides `Base::vf(double)`
};