C++中Overload,Override,Hide之间的区别

一. 简介
•Overload:
重载,指函数同名,但是参数个数不同、或者参数类型不同的多个实现。(如果参数相同但是仅仅返回值不同不是重载,编译器会报错。)

编译器判断重载函数:
•第一步,
是确定该调用中所考虑的重载函数的集合,该函数集合被称为候选函数(candidant function)。所谓候选函数就是与被调用函数同名的函数。

•第二步,分为两动作:第一个动作是编译器从第一步选出的候选函数中调出可行函数(viable function)。可行函数的函数参数个数与调用的函数参数个数相同,或者可行函数的参数可以多一些,但是多出来的函数参数都要有相关的缺省值;第二个动作是根据参数类型的转换规则将被调用的函数实参转换(conversion)成候选函数的实参。这里本着充分利用参数类型转换的原则,换句话说,尽可能的使用上参数类型转换。当然转换要以候选函数为转换的目标。如果依照参数转换规则没有找到可行函数,则该调用就是错误的,则说没有函数与调用匹配,属于无匹配情况(no match function)。

•第三步,从第二步中选出的可行函数中选出最佳可行函数(best match situation)。在最佳可行函数的选择中,从函数实参类型到相应可行函数参数所用的转化都要划分等级,根据等级的划分(ranked),最后选出最佳可行函数。

•Override:(想不到比较贴切的翻译)指在继承时,父类函数声明为 virtual , 子类重新声明和实现该函数(函数名和参数完全相同,返回值不做约束)。子类该函数可以声明为 virtual ,也可以不加,不做限制,但是如果该子类还会继续被重载,则最好也声明为 virtual 。正是因为有virtual和Override的机制,C++才能够实现多态。

•Hide:继承结构中的函数隐藏,指父类中声明了函数,子类中声明和定义了完全一致的函数,但是父类中函数没有声明为vitual,此时子类中的同名同参数函数会完全隐藏父类的函数。貌似和Override很像,但是其实现机制和Override完全不同,且会导致问题,应该避免使用。( virtual机制是使用虚表(vtable)实现的,虚表维护一个虚函数指针列表,但一个对象的某个虚函数被调用的时候,去虚表中查找并决定调用的是哪个函数,具体的实现,小编下次在讲。)


代码如下:

class Super
{
public:
void go() { cout << "go() called on Super" << endl; }
};
class Sub : public Super
{
public:
void go() { cout << "go() called on Sub" << endl; }
};
Sub mySub;
mySub.go(); // output: go() called on Sub
Super& ref = mySub;
ref.go(); //output: go() called on Super

也许你希望它会调用子类的函数,但这可能和你的预期完全不同。

二. 总结
重载overload,这个概念是大家熟知的。在同一可访问区内被声名的几个具有不同参数列的(参数的类型、个数、顺序不同)同名函数,程序会根据不同的参数列来确定具体调用哪个函数,这种机制就是重载。重载不关心函数的返回值类型,即返回类型不同无法构成重载。此外,C++ 中的const成员函数也可以构成overload。

总结一下重载的特征:
1、处在相同的空间中,即相同的范围内;
2、函数名相同;
3、参数不同,即参数个数不同,或相同位置的参数类型不同;
4、const成员函数可以和非const成员函数形成重载;
5、virtual关键字、返回类型对是否够成重载无任何影响。

覆盖override,是指派生类中存在重新定义的函数,其函数名、参数列、返回值类型必须同父类中的相对应被覆盖的函数严格一致,覆盖函数和被覆盖函数只有函数体(花括号中的部分)不同,当派生类对象调用子类中该同名函数时会自动调用子类中的覆盖版本,而不是父类中的被覆盖函数版本,这种机制就叫做覆盖,特征是:

1、不同的范围(分别位于派生类与基类);      
2、函数名字相同;      
3、参数相同;      
4、基类函数必须有virtual关键字。

针对上述两个概念,还有一个隐藏hide。所谓的隐藏,指的是派生类类型的对象、指针、引用访问基类和派生类都有的同名函数时,访问的是派生类的函数,即隐藏了基类的同名函数。隐藏规则的底层原因其实是C++的名字解析过程。在继承机制下,派生类的类域被嵌套在基类的类域中。派生类的名字解析过程如下:

1、首先在派生类类域中查找该名字。
2、如果第一步中没有成功查找到该名字,即在派生类的类域中无法对该名字进行解析,则编译器在外围基类类域对查找该名字的定义。

总结一下隐藏的特征:
1、如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。

2、如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。

(0)

相关推荐

  • 详解C++成员函数的override和final说明符的用法

    override 说明符 可使用 override 关键字来指定在基类中重写虚函数的成员函数. 语法 function-declaration override; 备注 override 仅在成员函数声明之后使用时才是区分上下文的且具有特殊含义:否则,它不是保留的关键字. 使用 override 有助于防止您的代码中出现意外的继承行为.以下示例演示在未使用 override 的情况下,可能不打算使用派生类的成员函数行为.编译器不会发出此代码的任何错误. class BaseClass { vir

  • C++中overload,override,overwrite的区别详细解析

    Overload(重载):在C++程序中,可以将语义.功能相似的几个函数用同一个名字表示,但参数或返回值不同(包括类型.顺序不同),即函数重载.(1)相同的范围(在同一个类中):(2)函数名字相同:(3)参数不同:(4)virtual 关键字可有可无. Override(覆盖):是指派生类函数覆盖基类函数,特征是:(1)不同的范围(分别位于派生类与基类):(2)函数名字相同:(3)参数相同:(4)基类函数必须有virtual 关键字. Overwrite(重写):是指派生类的函数屏蔽了与其同名的

  • 详谈c++11 final与override说明符

    如下所示: //final,override出现在形参列表以及尾置返回类型之后 #include <iostream> using namespace std; struct B{ virtual void f1(int) const; virtual void f2(int); void f3(int) final;//出错,final不能修饰非虚函数 }; struct D:B{ void f1(int) const override ;//去掉const将出错,必须和基类中的函数原型一致

  • C++中Overload,Override,Hide之间的区别

    一. 简介•Overload: 重载,指函数同名,但是参数个数不同.或者参数类型不同的多个实现.(如果参数相同但是仅仅返回值不同不是重载,编译器会报错.) 编译器判断重载函数:•第一步,是确定该调用中所考虑的重载函数的集合,该函数集合被称为候选函数(candidant function).所谓候选函数就是与被调用函数同名的函数. •第二步,分为两动作:第一个动作是编译器从第一步选出的候选函数中调出可行函数(viable function).可行函数的函数参数个数与调用的函数参数个数相同,或者可行

  • JS中typeof与instanceof之间的区别总结

    JavaScript 中 typeof 和 instanceof 常用来判断一个变量是否为空,或者是什么类型的.但它们之间还是有区别的: typeof typeof 是一个一元运算,放在一个运算数之前,运算数可以是任意类型. 它返回值是一个字符串,该字符串说明运算数的类型.typeof 一般只能返回如下几个结果: number,boolean,string,function,object,undefined.我们可以使用 typeof 来获取一个变量是否存在,如 if(typeof a!="un

  • JAVASCRIPT style 中visibility和display之间的区别

    当visibility被设置为"hidden"的时候,元素虽然被隐藏了,但它仍然占据它原来所在的位置. --------------------------------------------------------------- 例子: 复制代码 代码如下: <script language="JavaScript"> function toggleVisibility(me){ if (me.style.visibility=="hidde

  • 探讨Ajax中同步与异步之间的区别

    请求方式,分为GET与POST: GET 最为常见的HTTP请求,普通上网浏览页面就是GET.GET方式的参数请求直接跟在URL后,以问号开始.(JS中用window.location.search获得).参数可以用encodeURIComponent进行编码,使用方式: var EnParam = encodeURIComponent(param); URL只支持大约2K的长度,即2048字符数:使用GET进行AJAX请求时候会缓存导致出现的页面不是正确的,一般方法加random参数值:aja

  • .net中as和is之间的区别分析

    1.as 用于在兼容的引用类型之间执行转换,as 运算符类似于强制转换操作:但是,如果转换不可行,as 会返回 null 而不是引发异常.更严格地说,这种形式的表达式:expression as type,等效于expression is type ? (type)expression : (type)null,只是 expression 只被计算一次.注意,as 运算符只执行引用转换和装箱转换.as 运算符无法执行其他转换,如用户定义的转换,这类转换应使用 cast 表达式来执行 as操作符不

  • Java中ArrayList和LinkedList之间的区别_动力节点Java学院整理

    一.ArrayList ArrayList是一个可以处理变长数组的类型,这里不局限于"数"组,ArrayList是一个泛型类,可以存放任意类型的对象.顾名思义,ArrayList是一个数组列表,因此其内部是使用一个数组来存放对象的,因为Object是一切类型的父类,因而ArrayList内部是有一个Object类型的数组类存放对象.ArrayList类常用的方法有add().clear().get().indexOf().remove().sort().toArray().toStri

  • Jquery中children与find之间的区别详细解析

    首先看一段HTML代码,如下: 复制代码 代码如下: <table id="tb">            <tr>                <td>0</td>                <td>1</td>                <td>2</td>            </tr>            <tr>               

  • vue中计算属性(computed)、methods和watched之间的区别

    前言 本文主要给大家介绍了关于vue中计算属性(computed).methods和watched之间的区别,分享出来供大家参考学习,下面来一起看看详细的介绍: 计算属性 和普通属性一样是在模板中绑定计算属性的,当data中对应数据发生改变时,计算属性的值也会发生改变. Methods methods是方法,只要调用它,函数就会执行. 相同:两者达到的效果是同样的. 不同:计算属性是基于它们的依赖进行缓存的,只有相关依赖会发生改变时才会重新求职.只要相关依赖未改变,只会返回之前的结果,不再执行函

  • Java中List Set和Map之间的区别_动力节点Java学院整理

    Java集合的主要分为三种类型: • Set(集) • List(列表) • Map(映射) 要深入理解集合首先要了解下我们熟悉的数组: 数组是大小固定的,并且同一个数组只能存放类型一样的数据(基本类型/引用类型),而JAVA集合可以存储和操作数目不固定的一组数据. 所有的JAVA集合都位于 java.util包中! JAVA集合只能存放引用类型的的数据,不能存放基本数据类型. 世间上本来没有集合,(只有数组参考C语言)但有人想要,所以有了集合 有人想有可以自动扩展的数组,所以有了List 有的

随机推荐