混迹于C++ 之重载与覆盖(还有隐藏)
来源:互联网 发布:淘宝卖家后台 编辑:程序博客网 时间:2024/04/28 01:37
摘自《高质量程序设计指南》林锐
重载与覆盖
成员函数被重载的特征是:
-具有相同的作用域(即同一个类定义中)--如果位于不同的作用域,则为隐藏。
-函数名字相同。
-参数类型/顺序或数目不同(包括const参数和非const参数)。
-virtual关键字可有可无。
覆盖是指派生类重新实现(或者改写)了基类的成员函数,其特征是:
-不同的作用域(分别位于派生类和基类中)。
-函数名称相同。
-参数列表相同。
-基类函数必须是虚函数。(用virtual关键字)。--如果没有virtual关键字,则为隐藏。
注:覆盖:使用虚函数virtual 一般不用具体的实现函数virtual fun() = 0;即故意要让继承者重新实现函数功。
而隐藏则可以暂时在子类里屏蔽了基类的功能函数,重新实现函数名相同,但参数可以不同。
综上,覆盖是一种特殊的隐藏。
程序示例1
#include<iostream>using namespace std;class Base{public: void f(int x){cout<<"Base::f(int)="<<x<<endl;} void f(float x){cout<<"Base::f(float)="<<x<<endl;} virtual void g(void){cout<<"Base::g(void)."<<endl;}};class Derived:public Base{public: virtual void g(void){cout<<"Derived::g(void)."<<endl;}};int main(void){ Derived d; Base *pb=&d; pb->f(42); //Base::f(int)=42 pb->f(3.14f); //Base::f(float)=3.14 pb->g(); //Derived::g(void). return 0; }
有时候,程序员希望作“跨越类边界的重载”,但是重载机制只能作用于同一作用域中,C++提供类
另一种机制--隐藏,它是指派生类的成员函数遮蔽了与其同名的基类成员函数。
虽然还没达到完美的要求,但C++使用了这种策略(原因《The Designed and Evolution of C++》).
示例2
#include<iostream>using namespace std;class Base{public: virtual void f(float x){ cout<<"Base::f(float)="<<x<<endl;} void g(float x){cout<<"Base::g(float)="<<x<<endl;} void h(float x){cout<<"Base::h(float)="<<x<<endl;}};class Derived:public Base{public: virtual void f(float x){ cout << "Derived::f(float)"<<x<<endl; } void g(int x){ cout << "Derived::g(int)"<<x<<endl; } void h(float x){ cout << "Derived::h(float)"<<x<<endl;}};int main(){ Derived d; Base *pb=&d; Derived *pd=&d; //程序的行为仅仅依赖于对象的真实类型 pb->f(3.14f); //动态绑定:Derived::f(float)=3.14 pd->f(3.14f); //动态绑定:Derived::f(float)=3.14 //不好:程序的行为依赖于指针的静态模型 pb->g(3.14f); //静态绑定:Base::g(float)=3.14 pd->g(3.14f); //静态绑定:Derived::g(float)=3 //此处3.14被强制转化为一个int类型的临时变量,而本意是想使用跨越类边界的重载 //不好:程序的行为依赖于指针的静态模型 pb->h(3.14f); //静态绑定:Base::h(float)3.14 pd->h(3.14f); //静态绑定:Derived::g(float)=3 return 0;}
总结:覆盖是隐藏的一种特殊,它改写类基类的成员函数,但是隐藏却没被改写成员函数。
而重载是根据参数的不同,区分使用同一作用域中同名的函数。
另外,
如果确实想使用所谓的“跨越类边界的重载”,可以在派生类定义中的任何地方显示的使用using关键字,
示例2中红色处:
写成 using Base ::g;
void g(int x){ cout << "Derived::g(int)"<<x<<endl; }
或者使用调用传递
void g(float x){Base::g(x);}
void g(int x){ cout << "Derived::g(int)"<<x<<endl; }
显然使用using关键字比较省事。
参数的默认值的常见错误
http://blog.csdn.net/xydkd/article/details/7194669
- 混迹于C++ 之重载与覆盖(还有隐藏)
- C++:重载、覆盖与隐藏
- C++:重载、覆盖与隐藏
- 混迹于C++ 之运算符重载
- c++(成员函数的)重载、覆盖与隐藏
- (1) C++:重载、覆盖与隐藏
- c++(重载、覆盖、隐藏)
- c++(重载、覆盖、隐藏)
- c++(重载、覆盖、隐藏)
- c++(重载、覆盖、隐藏)
- c++(重载、覆盖、隐藏)
- c++(重载、覆盖、隐藏)
- c++(重载、覆盖、隐藏)
- c++(重载、覆盖、隐藏)
- c++(重载、覆盖、隐藏)
- c++(重载、覆盖、隐藏)
- c++(重载、覆盖、隐藏)
- c++(重载、覆盖、隐藏)
- Steve Jobs’ Speech at Stanford University
- Struts2的类型转换器
- Java网络爬虫的实现
- LINUX:用C语言来模拟密码输入
- UCOS II两个任务的模板
- 混迹于C++ 之重载与覆盖(还有隐藏)
- 黑客攻防技术宝典--web实战篇(第二版)人民邮电出版社
- android开发控件——listview1(入门)
- OGRE分析之设计模式(一)
- 血的教训之 ---- 字符集
- 一台计算机上如何装多个Tomcat服务器
- .Net 多文件上传
- delphi中WebBrowser的parent改变时变成空白问题的解决
- 五种开源协议的比较(BSD,Apache,GPL,LGPL,MIT)