C++的多态与重载,覆盖,隐藏

C++的多态与重载,覆盖,隐藏

最近在看C++语言的设计与演化,学习了很多的知识,C++之父确实名副其实,写了一些读书笔记还没整理好发上来,后面会慢慢整理好~这种好书真的值得仔细的读好多遍

今天在看书时,又看到了重载,覆盖,隐藏这三个问题,以前对这些东西一知半解,仅仅停留在问题的表面上,今天仔细的研究了下,发现这个问题实际上与C++的多态性非常相关,理解了这个对C++的OO思想有着很大的帮助。
在网上如果搜索“重载覆盖隐藏”这几个关键字,会搜到很多相关的文章,但大多数都不是我想要的结果,大多是贴贴代码,然后告诉你:看这就是这几个的区别~,这样是很不好的~,我今天就写写我关于这几个性质的认识,当然我参考了C++ primer(5th){这真是一本神书!}


在说起正文之前,首先我先提出几个问题:

  1. 什么是C++的多态性
  2. 怎样才能使用多态
  3. 为什么要按照2问题的方式才能使用(其实就是怎样使得编译器实现多态的性质)

回答
  1. C++的多态:多态在面对对象编程的技术中占有重要的地位,简单来说,就是通过虚函数的使用,实现一个接口,多个实现的效果,相当于一个函数接口可以有多个不同的实现;这里分为静态多态与动态多态两种;
    静态多态:这个是在编译时期就确定了调用函数,我觉得重载应该算一种静态多态
    动态多态:只有在编译时期才能确定具体的调用那个函数,这个就是虚函数的性质了吧
    (当然这都是我的理解,不是很严谨,要是有什么错误的地方欢迎指正,共同进步~)注:可以在C++ Primer (5th)中p537找到Lippman大师的解读~
  2. 如何使用:这里主要说一下动态的,这里如果要使用虚函数,那么必须使用基类的指针或者绑定进行调用,这时候可以根据其指向的对象不同,运行时确定具体应当调用哪个虚函数。
  3. 如何实现的:这里细节很多,可以知道这个是通过一个虚函数表实现的(当然这里涉及到了很多知识,这些知识在<深入探索C++面对对象模型>一书中可以找到,我就不班门弄斧啦,还需继续修炼)。
  4. 同时,我还要贴出C++中的函数调用解析过程(假设调用p->mem(),或obj.men()):
    1. 首先确定指针或者对象的静态类型;
    2. 在静态类型对应的类中查找函数调用,若没有,则向基类方向查找,直到顶端;若仍然没有查到,则报错
    3. 若找到了mem,进行类型检查,若调用合法,则:
      1. 若是通过引用或者指针调用,则进行虚调用,动态绑定
      2. 若mem不是虚函数或者是通过对象进行的调用,则产生一个常规的调用。

上面的规则非常重要
因此我们知道了名字查找是先于类型检查的; 那么我们就来谈谈隐藏吧: 从各路资料中我们了解到:隐藏有两种方式:
第一种:派生类中的函数参数类型不同,这时候就无论你是不是虚函数了;
第二种:不是虚函数(没有加关键字virtual),这个时侯如果派生类重新写了一编,这时候就又是隐藏了
在我看到这个问题的时候,我想起了C++语言设计与演化中的一个规则:
C++中的保护机制 这里说明了:c++保护的是访问权不是可见性,具体是以一个类内和类外有着同名变量却不同类型时所造成的奇异性,(这个我会整理一下也发出来的~)
这里其实就是一个访问权的问题,为什么会产生隐藏呢,因在派生类(内层)与基类(外层)中有重名时,在派生类的作用域内就会隐藏外层的作用域;书中给出了这样一个例子
{
int a;
class x{private:int a};
class xx:public x{void f(){cout<<a;};};
}
这个例子实际中会出现编译错误,因为首先x::a已经将全局的a屏蔽掉,因此当函数想访问a时由于a是private的,因此会出现访问权的错误;
如果是可见性,则会去访问全局的a;
c++他爹说,这样会消除奇异性,设想若为可见性,则private改为public时,则函数悄悄由全局a变成了类成员a,因此便消除了这个错误。非常赞!

在了解了这些之后可以翻看一下C++ primer的p549看看示例代码,同时按照名称查找规则模拟一下,应该就了解什么是隐藏了:首先因为重名,若类型不对,报错,类型对了,但不是虚函数,这个就没啥关系了……就直接调用了呗~


在解决了隐藏之后,覆盖就简单了,我们因此也知道了基类与派生类中的虚函数必须有相同的形参列表了,如果不一样,要么就被隐藏了,要么就报错了……这个时侯判断是不是虚调用,就看看调用的是不是基类指针或引用,然后在检查检查基类中是否有这个函数,并且定义为了虚函数,那么就产生了虚调用了~

end


上面我说了下我对这几个的简单理解,当然其中不免有些理解错误的地方,希望大家能够指出来让我改正~,总之C++语言真的不是那么容易掌握,即使掌握了也还有很长的路要走,每次重温时总会有新的理解~继续努力!


参考文献:
Lippman S B, Lajoie J, Moo B E. C++ Primer[M]. Addison-Wesley, 2005.
Stroustrup B. The design and evolution of C++[M]. Pearson Education India, 1994.



Previous     Next
SureD /
Published under (CC) BY-NC-SA in categories programming language  tagged with c++ 
分享到: 更多
>