C++ OOP--函数解析过程

C++ OOP--函数解析过程

May 30, 2017
C++, OOP

类的作用域 #

名称查找优先,对于编译器来说,优先寻找名称一致的函数,再关心类型的问题。

编译器在进行名称查找的顺序: 直接类定义 -> 父类定义 -> 祖宗类定义。但是,搜索顺序是按照静态类型开始的,结合上面的动态绑定,如果你的指针类型是父类,那么即使实体是个子类也不会在子类域中搜索,直接从父类开始搜索,因为编译阶段无法做动态绑定。

隐藏&重载&覆盖 #

这个概念刚开始学C++的人可能会比较迷。

隐藏 #

隐藏是在继承中出现的概念。基类与派生类有一个同名函数,则无论是否参数类型一致,基类的函数都会被隐藏掉。这个隐藏的意思,与Java中的override是否一致,我觉得不一致,但是效果一致。因为编译器在搜索名字的时候首先搜索派生类的函数,然后看参数,如果参数类型对的上就调用,对不上就报错。所以根本调用不到基类的函数,实现了隐藏。但是,C++中基类的函数还是存在的,Java中是直接将父类的函数段重写,父类的函数完全从代码段消失了。 既然还存在,就意味着可以访问。使用using关键字调用函数可以直接调用基类被隐藏的函数,可以说using改变了编译器名字查找的顺序。

对于虚函数,我们要求参数类型必须一致,就是这个原因。要实现动态绑定就必须使得当查找到函数名时,此函数可以被调用,而不是报个错说参数不一致。

这个规则是可以类推出来的,从命名上我们就可以窥探出这个东西有什么特质。

比如作为成员函数,就是可以被隐藏,无论是虚函数还是普通函数都是可以的。虚函数可以被普通函数隐藏,普通函数也可以被虚函数隐藏,其他一些概念一样可以用命名来推导出来。

重载 #

重载是对于函数来说的,与类间继承没有关系。对于一个普通函数,即不存在任何的类中的独立函数,重载的概念很清晰,就是相同的函数名不同的参数列表

对于成员函数来说,在同一个类中,可以重载,重载的概念也是一样的。

覆盖 #

覆盖与上面的东西又不一样,但是这个不是C++中的重点概念。覆盖是对于基类的虚函数来说的,派生类写一个名称、参数类型完全相同的函数,可以实现覆盖,其实就是虚函数的那一套东西。

只要分清楚,隐藏和覆盖是在父子间作用的,重载是同级内作用的就可以了。

那么有一个问题,很恶心,哈。 就是基类的虚函数被重载了,有很多个版本,子类在覆盖的时候,可以选择覆盖哪个版本。一样是使用using修饰符来将基类的函数作用域同步到当前作用域上来,这样只有对需要覆盖的版本进行覆盖就行了,其他的就使用基类的实现。