理解c++语言的重载、覆盖和隐藏

来源:互联网 发布:文都网络 编辑:程序博客网 时间:2024/06/01 07:37

理解c++语言的重载、覆盖和隐藏

关于c++语言的重载、覆盖和隐藏的文章很多也很长,但还是基本都没能说到点子上。
本来文章的标题应该叫《c++类层次结构中的屏蔽现象》,但是为了博取眼球,以及搜索引擎优化不得不用上面那个标题,当然了,目的是为了理解c++中的重载、覆盖和隐藏现象。
好了,好了,我要吹牛了,大家快跑啊。等等,csdn搞了markdown这个新玩意,我日,不会用。。。


同一个类

重载发生在同一个类中,比较简单,没什么好说的。


继承,也就是就类层次结构

这个看上去比较复杂了,会出现下列几种情况的组合

参数 virtual 现象 参数相同 有virtual 覆盖 参数相同 无virtual 隐藏 参数不同 有virtual 隐藏 参数不同 无virtual 隐藏

那么问题来了,覆盖和隐藏是个什么鬼?到底有什么区别?是不是很纠结?是不是一下子就迷茫了?

其实我可以很负责任的告诉你,它们根本没区别。
现在你可以把上面那个表忘掉了。

我发明了一个词,叫屏蔽(shield)

在继承体系或者类层次结构的派生类中出现了与基类同名的方法时,派生类的方法将会屏蔽已经继承到的基类的方法,不管参数是否相同,也不管是否有virtual关键字。 这是c++编译器强制的,没有商量的。

举例,假设基类B中有一个名字叫f1的方法,派生类D中也有一个名叫f1的方法,那么不管这两个方法是否参数相同,也不管它们是否有virtual关键字,派生类的f1方法将自动屏蔽基类的f1方法。意思就是说我们无法通过派生类D来访问基类B的f1方法了,但是基类B的方法确确实实是已经被派生类继承过来了,可以把这种屏蔽理解为派生类将同名的基类方法访问控制权限设为protected。

那么c++编译器是通过什么途径来达到这种屏蔽效果的呢?有两种方式,具体如下:
1,限制访问
还是上面那个例子,D本来已经继承到了B的f1方法,但是同名同参数的情况下,我们无法通过D来调用到B的f1。比如,

D d;d.f1();我们调不到B的f1。

2,编译出错。
你可能会说,那好办啊,参数不一样不就行了。比如B的f1是void f1(),然后D的f1是void f1(int),然后

D d;d.f1();这样编译会出错,error C2660: “D::f1”: 函数不接受 0 个参数。

屏蔽似乎起作用了。

那么问题来了,既然D继承到了B的方法,那我们可不可以突破这种屏蔽效果来强撸B的方法呢?答案是可以。用向上强制转换(upcasting)。

B* pB = &D;

注意,这个upcasting对于同参数且都使用virtual关键字的方法会触发多态,触发了多态就意味着我们再也没法调用B的那个被屏蔽的方法了,也就是说B的方法被D永久的屏蔽了。


多态

文章到了这里,如果你能看懂上面的论述,你将会开始怀疑人生,永久屏蔽?wtf…

是的,要的就是永久屏蔽,不然多态从技术上就无法实现


代码

#include <iostream>using namespace std;class CBase{public:    virtual void f1(){cout<<"B::f1()"<<endl;}    void f2(){cout<<"B::f2()"<<endl;}    virtual void f3(){cout<<"B::f3()"<<endl;}    void f4(){cout<<"B::f4()"<<endl;}};class CDerive : public CBase{public:    virtual void f1(){cout<<"D::f1()"<<",";CBase::f1();}    //参数相同,有virtual------覆盖    void f2(){cout<<"D::f2()"<<",";CBase::f2();}            //参数相同,无virtual------隐藏    virtual void f3(int){cout<<"D::f2()"<<",";CBase::f3();} //参数不同,有virtual------隐藏    void f4(int a){cout<<"D::f4(int)"<<",";CBase::f4();}    //参数不同,无virtual------隐藏};int main(){    //正常访问    CDerive d;    d.f1();    d.f2();    d.f3(1);//d.f3();编译报错,error C2660: “CDerive::f3”: 函数不接受 0 个参数    d.f4(1);//d.f4();编译报错,error C2660: “CDerive::f4”: 函数不接受 0 个参数    cout<<endl;    //强制访问    CBase* pB = &d;    pB->f1();    pB->f2();    pB->f3();    pB->f4();    getchar();    return 0;}

运行

这里写图片描述

原创粉丝点击