[C++再学习系列] 派生类函数的重实现规则(override-覆盖)

简介:

  对于用过C++的人大体都清楚:派生类可以重实现基类中声明为virtual的函数,并且很清楚如果想实现正确的重写,必须满足:派生类重实现的函数的所有属性和基类virtual函数一致,即函数签名,const限制均一样。同时为了更好地传达代码意图,重实现的virtual函数最好添加冗余的virtual关键字。

  上面这些是基本要求,对于重实现,还有3个需要注意的地方:

  1) 保证可替换性: 任何派生类都必须遵守基类所承诺的前条件和后条件。当然改写后函数可以要求更少保证更多,反之不行。

  2) 永远不要修改默认参数。切记:默认参数并非函数签名的组成部分,修改重实现函数的默认参数,并不会导致重实现失败,但会导致糟糕的默认参数错误。对于调用者而言,同一个对象的成员函数会不加提示地根据自己访问所使用的静态类型而接受不同的参数。换句话说,重实现函数的默认参数并不具有多态属性。

  3)  谨防基类重载(overload)函数被重实现函数所隐藏(overwrite)。(这和C++的名字查找相关)

示例1:默认参数问题

class Base {

  virtual void Foo( int x = 0 );

};

class Derived : public Base {

  virtual void Foo( int x = 1 );       // poor form, and surprise-inducing

};

Derived *pD = new Derived;

pD->Foo();                       // invokes pD->Foo(1)

Base *pB = pD;

pB->Foo();                       // invokes pB->Foo(0)

示例:隐藏基类重载函数

class Base{

  virtual void Foo( int );

  virtual void Foo( int, int );

  voidFoo( int, int, int );

};

class Derived : public Base {

  virtual void Foo( int );     // overrides Base::Foo(int), but hides theothers

};

Derived d;

d.Foo( 1 );                 // ok

d.Foo( 1, 2 );             // error (oops?)

d.Foo( 1, 2, 3 );         // error (oops?)

  问题产生的原因:C++编译器的编译过程分3步:名字查找,重载解析和访问性检查。为加快名字查找速度,编译器是逐步扩大名字查找范围的。以上述例子为例:d.Foo( 1, 2 ); 在名字查找时,编译器首先发现派生类存在Foo函数,并停止名字查找;接着进行函数的重载解析,并发现派生类中,并未找到合适函数签名的Foo函数,报错!

  解决方案:使用using引入基类的特定名字(见<Using声明和指令的工作原理>)。

class Derived : public Base {// …

  virtual void Foo( int );      // overrides Base::Foo(int)

  using Base::Foo;              // bring the other Base::Foooverloads into scope

};

相关文章:

揭秘:C++编译器的函数编译流程

[C++再学习系列] Using声明和指令的工作原理

---------------------------------------------------

兄弟的公司:立即购--手机购物,诚信网购

欢迎转载,请注明作者和出处。

本文转自 zhenjing 博客园博客,原文链接:http://www.cnblogs.com/zhenjing/archive/2010/12/02/override_overwrite_overload.html   ,如需转载请自行联系原作者


相关文章
|
7天前
|
设计模式 安全 算法
【C++入门到精通】特殊类的设计 | 单例模式 [ C++入门 ]
【C++入门到精通】特殊类的设计 | 单例模式 [ C++入门 ]
16 0
|
1天前
|
C++ 编译器 程序员
C++ 从零基础到入门(3)—— 函数基础知识
C++ 从零基础到入门(3)—— 函数基础知识
|
5天前
|
编译器 C++
【C++】继续学习 string类 吧
首先不得不说的是由于历史原因,string的接口多达130多个,简直冗杂… 所以学习过程中,我们只需要选取常用的,好用的来进行使用即可(有种垃圾堆里翻美食的感觉)
7 1
|
5天前
|
算法 安全 程序员
【C++】STL学习之旅——初识STL,认识string类
现在我正式开始学习STL,这让我期待好久了,一想到不用手撕链表,手搓堆栈,心里非常爽
13 0
|
5天前
|
存储 安全 测试技术
【C++】string学习 — 手搓string类项目
C++ 的 string 类是 C++ 标准库中提供的一个用于处理字符串的类。它在 C++ 的历史中扮演了重要的角色,为字符串处理提供了更加方便、高效的方法。
15 0
【C++】string学习 — 手搓string类项目
|
6天前
|
自然语言处理 编译器 C语言
【C++】C++ 入门 — 命名空间,输入输出,函数新特性
本文章是我对C++学习的开始,很荣幸与大家一同进步。 首先我先介绍一下C++,C++是上个世纪为了解决软件危机所创立 的一项面向对象的编程语言(OOP思想)。
32 1
【C++】C++ 入门 — 命名空间,输入输出,函数新特性
|
6天前
|
Java C++ Python
【C++从练气到飞升】06---重识类和对象(二)
【C++从练气到飞升】06---重识类和对象(二)
|
6天前
|
编译器 C++
【C++从练气到飞升】06---重识类和对象(一)
【C++从练气到飞升】06---重识类和对象(一)