Changing the Overridden Method’s Characteristics
修改重写方法的特征
在大多数情况下,我们重写(override)一个 virtual 方法是为了改变它的实现。然后,有时我们却想改变该 virtual 方法的其他的特征,这往往会带来一系列问题。
1)改变方法的返回值类型
通常,子类在重写方法时,要保持与父类一致的函数原型,方法的实现可以改变,但是原型需要保持不变。
然而,事实却并非如此。在C++中,如果父类的 virtual 方法的返回值类型是某个类(假定为类A)的指针或者引用,那么在子类中 override 该方法时,可以将其返回值改变为子类(类A的子类)的指针或者引用。这就是所谓的协变返回类型(covariant return types)。当父类与子类工作在 parallel hierarchy 中时,这个 feature 将会派上用场。注意,parallel hierarchy 是指,一个层次结构与另一个层次结构没有相交,但是存在联系。
我们来考虑一个樱桃果园模拟程序,如下图所示,就是一个parallel hierarchy ,
现在假定 Cherry Tree 类有一个 pick() 方法,这个方法的功能是从树上摘下一个樱桃:
很自然,在 BingCherryTree 子类中,我们会想 override 该 pick() 方法。由于 BingCherry 是一个 Cherry,在下面的代码中,我们可以使方法的原型保持不变。BingCherry指针将自动转换为 Cherry 指针(向上转型)。
以上的实现很好,但是,能不能更进一步呢?因为我们知道,BingCherryTree 返回的实际上是一个更为具体的BingCherry,因此,我们可以通过修改返回值类型(将 Cherry * 修改为 BingCherry *)向BingCherryTree 类的用户指明这一点,如下所示:
这里一个好的方法来判断是否可以在重写方法时改变其返回值类型:我们可以考虑在修改返回值类型后,原来已有的代码是否仍然可以良好运行。在之前的示例中,修改返回值类型没有问题,因为假定 BingCherryTree 类的 pick() 方法总是返回 Cherry * 的代码仍然可以成功编译并正常运行。道理很简单,BingCherry 是一个 Cherry,在返回 Cherry * 的地方返回 BingCherry * 总是没有问题的。
需要注意的是,我们不能在重写方法时,将返回值类型修改为完全不想关的类型,例如 void *。
小结:对于父类中的某个 virtual 方法,只要子类中某个方法与该 virtual 方法的名字以及参数列表完全相同,那么编译器即认为子类将 override 该方法,此时如果返回值类型兼容,那么没有问题,如果不兼容,编译器将会报错。
2) 修改方法的参数
如果在子类的定义中使用父类 virtual 方法的名称,但参数与父类中同名方法的参数不同,那么这不是在 override 父类的方法,而是在创建一个新方法。而父类原始的同名方法将被隐藏。
当然,我们可以使用一种较为晦涩的技术兼顾被隐藏的方法,那就是使用 using 关键字。
小结:对于非虚方法,只要重名即为隐藏。对于 virtual 方法,名字以及参数完全一样则认为子类试图 override 父类方法,如果返回值类型兼容则 override 成功,返回值类型不兼容,则报错。
3) The override keyword(C++11)
有的时候,我们本意是想 override 父类的一个 virtual 方法,但是可能一不小心,就变成隐藏父类的 virtual 方法了。来看以下例子:
我们可以通过引用来调用 Method() 方法,如下所示:
代码将正确地调用 Sub 类重写的 Method()。现在假定 override Method() 时,我们使用了int(而非double,如此一来,改变了参数类型,不再时override),如下所示:
显然,以上代码并没有 override Method() 方法,而是创建了一个新的 virtual 方法(隐藏了父类的 Method() 方法)。如果我们仍然试图像刚刚一样去调用 Method(),将会调用的是 Super 的 Method(),而非 Sub 类中定义的那个方法(多态)。
如果我们在实际的工程中,由于需求变更而修改了父类的某个 virtual 方法的函数原型,而此时却没有相应改变子类的实现。那么实际在子类中就是创建了一个新的 virtual 方法(同时,隐藏了父类的 virtual 方法),而不是 override 了父类的 virtual 方法。
此时,根据 C++11 标准,我们可以采用 override 关键字来避免这种情况,如下所示:
Sub 的定义将导致编译器报错,因为 override 关键字表明我们要重写 Super 类的 Method() 方法,但在 Super 类中的 Method() 方法参数为 double,因此在子类中并没有实现 override。
Changing the Overridden Method’s Characteristics的更多相关文章
- What Influences Method Call Performance in Java?--reference
reference from:https://www.voxxed.com/blog/2015/02/too-fast-too-megamorphic-what-influences-method-c ...
- Override is not allowed when implementing interface method Bytecode Version Overriding and Hiding Methods
java - @Override is not allowed when implementing interface method - Stack Overflow https://stackove ...
- CLR via C# 3rd - 08 - Methods
Kinds of methods Constructors Type constructors Overload operators Type con ...
- Java Interview Reference Guide--reference
Part 1 http://techmytalk.com/2014/01/24/java-interview-reference-guide-part-1/ Posted on January 24, ...
- Java Knowledge series 7
Pepole who make a greate contribution on common libaraies deserve our respect. Component(Widget) / S ...
- Using default security password
不展示Using default security password的解决办法: import org.springframework.context.annotation.Bean; import ...
- 关于C#你应该知道的2000件事
原文 关于C#你应该知道的2000件事 下面列出了迄今为止你应该了解的关于C#博客的2000件事的所有帖子. 帖子总数= 1,219 大会 #11 -检查IL使用程序Ildasm.exe d #179 ...
- spring mvc DispatcherServlet详解之前传---FrameworkServlet
做项目时碰到Controller不能使用aop进行拦截,从网上搜索得知:使用spring mvc 启动了两个context:applicationContext 和WebapplicationCont ...
- Java基础知识【上】(转载)
http://blog.csdn.net/silentbalanceyh/article/details/4608272 (最终还是决定重新写一份Java基础相关的内容,原来因为在写这一个章节的时候没 ...
随机推荐
- 直播源格式转换教程——rtmp/rtsp/http/m3u8!!
之前寻找直播源,发现好多rtmp开头的,或者是rtsp开头的,但是ATV里面的个人链接是支持m3u8格式的.怎么办?小编发现了几个规律,网友可作参考.现在流行的直播地址差不多就这几种需要说明的是并不是 ...
- .Net开源数据库设计工具Mr.E For Linq (EF 6.1) 教程(二)级联删除和触发器
1.建立级联删除 Mr.E的级联删除并非数据库自带那个级联删除,而是Mr.E自带的,所以它能触发你C#里面编写的触发器. 首先,建立级联删除关系,如下图有两个表,UserInfo和UserDocume ...
- Filter介绍
Filter可人为是Servlet的一种“加强版”,它重要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理,是个典型的处理链.使用Filter的完整的流程是:Filt ...
- iOS UIView的简单渐变效果
这里主要用到了ios4.0以后 UIView的类方法 animateWithDuration: 函数原型包括以下类方法 + (void)animateWithDuration:(NSTimeInter ...
- [rsync+inotify]——监控客户端文件变化,rsync同步到服务器
关于rsync的配置请参考博文:http://www.cnblogs.com/snsdzjlz320/p/5630695.html 实验环境 (1) Rsync服务器:10.0.10.158 (2) ...
- Teamwork——Week4 团队项目之NABC
项目框架——NABC模型 一.N(Need需求) 我们组主要的用户对象是第三小组——UI小组的同学们,因此我们的用户需求就是他们的数据需求. 1)提供给UI小组整理好的数据库,和前一组讨论好数据结构. ...
- Jquery $.getJSON()设置同步
如下: $.ajaxSettings.async = false; $.getJSON('/AjaxSwitchDynamicInfo/GetPortUsedCount.cspx', { switch ...
- Netsharp快速入门(之16) Netsharp基础功能(权限管理)
第5章 Netsharp基础功能 5.1 权限配置 5.1.1 功能权限 1.配置权限功能点,打开平台工具-基础业务-操作管理 2.选择资源节点为销售订单,点添加常用操作,添加完成后 ...
- Oracle中定义package以及存储过程的使用
使用scott账户下的dept表: select * from dept order by deptno; 10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS 30 S ...
- 读《我是一只IT小小鸟》有感
时间太瘦,指缝太宽.一晃一学期过去了,有些迷茫,但也相信未来是美好的.当我看完<我是一只IT小小鸟>这本书之后,心中更是感慨万千.每一个励志的故事都值得欣赏.深思,甚至我还幻想 ...