C++隐藏和覆盖

来源:互联网 发布:淘宝法莎莉雅手办 编辑:程序博客网 时间:2024/05/21 09:26
重载、覆盖、隐藏有着“千丝万缕”的关系,很容易混淆,就简单梳理了一下。

 

隐藏

覆盖

范围

基类与派生类

基类与派生类

关键点

基类可以不为虚函数,也可以为虚函数

基类必须为虚函数;(这个很重要,虚函数决定了基类或派生类对象的指针/引用的动态映射)

相同点

基类中多个函数重载,一旦一个被子类隐藏,所有的都将被隐藏

基类中多个函数重载,一旦一个被子类覆盖(也是隐藏),所有的都将被隐藏

不同点

基类与派生类函数名相同(参数数量、参数类型、返回值类型可以不同)

基类与派生类函数完全一致(函数名、参数数量、参数类型、返回值类型完全相同)

 

后来google了一下,在stackoverflow中发现了下面的一个总结,觉得很好,就拿过来了。

What is function hiding?
1.什么是函数隐藏?
... is a form of name hiding. A simple example:


下面的例子是一种作用域形式的隐藏。

void foo(int);namespace X{    void foo();    void bar()    {    //不能够调用::foo,因为X::foo将它隐藏。        foo(42); // will not find `::foo`        // because `X::foo` hides it    }}

 

This also applies to the name lookup in a base class:

上面的作用域形式隐藏同样可以被应用于基类和子类之间:

class Base{public:    void foo(int);};class Derived : public Base{public:    void foo();    void bar()    {    //不能够调用Base::foo,因为Derived::foo将它隐藏。        foo(42); // will not find `Base::foo`        // because `Derived::foo` hides it    }};

 

What is function overriding?
2. 什么是函数覆盖?
This is linked to the concept of virtual functions. [class.virtual]/2
函数覆盖和虚函数紧密相关。

If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list, cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides Base::vf.
如果一个成员虚函数vf在基类和派生类中都被声明,vf直接或间接继承于基类,派生类vf具有基类相同的函数名、参数列表、const和volatile修饰、ref-qualifier,就像在Base::vf声明的一样,这时Derived::vf(不管有无virtual)覆盖了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 &&; // 覆盖基类的vf   overrides `Base::vf(int) const &&`    void vf2(/*int*/);     // 没有覆盖       does NOT override `Base::vf2`    Derived* vf3(int);     // 覆盖           DOES override `Base::vf3` (covariant return type)};

The final overrider becomes relevant when calling a virtual function: [class.virtual]/2

A virtual member function C::vf of a class object S is a final overrider unless the most derived class of which S is a base class subobject (if any) declares or inherits another member function that overrides vf.
I.e. if you have an object of type S, the final overrider is the first overrider you see when traversing the class hierarchy of S back to its base classes. The important point is that the dynamic type of the function-call expression is used in order to determine the final overrider:

Base* p = new Derived;p -> vf();    // dynamic type of `*p` is `Derived`Base& b = *p;b  . vf();    // dynamic type of `b` is `Derived`

 

What is the difference between overriding and hiding?
3. 覆盖和隐藏的区别是什么?
Essentially, the functions in the base class are always hidden by functions of the same name in a derived class; no matter if the function in the derived class overrides a base class' virtual function or not:
从本质上讲,基类的函数总是被派生类的同名函数隐藏;无论派生类的是否覆盖基类的虚函数。

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)`};

To find a function name, the static type of an expression is used:

Derived d;
d.vf(42);   // `vf` is found as `Derived::vf()`, this call is ill-formed
            // (too many arguments)

How do they relate to function overloads?
4. 覆盖、隐藏和重载有什么关系?

As "function hiding" is a form of name hiding, all overloads are affected if the name of a function is hidden:
“函数隐藏”是一种函数名上的隐藏,所有重载函数都被隐藏一旦有一个函数被隐藏。

class Base{private:    virtual void vf(int);    virtual void vf(double);};class Derived : public Base{public:    void vf();     //基类中的两个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)`};




 





 

0 0