高质量程序设计指南--重载 覆盖 隐藏
来源:互联网 发布:知乎账号 编辑:程序博客网 时间:2024/04/20 15:47
成员函数的重载、覆盖与隐藏(书摘)
——《高质量程序设计指南》
成员函数的重载,覆盖(override,也叫改写)与隐藏(也叫遮蔽)很容易混淆,程序员必须搞清楚概念,否则调用结果可能与期望不符。
1. 重载与覆盖
成员函数被重载的特征是:
具有相同的作用域(即同一个类定义中);
函数名字相同;
参数类型,顺序或者数目不同(包括const参数和非const参数)
Virtual关键字可有可无;
覆盖是指派生类重新实现(或者改写了)基类的成员函数,其特征是:
不同的作用域(分别位于派生类和基类中);
函数名称相同;
参数列表完全相同;
基类函数必须是虚函数;
如下示例,函数Base::f(int)与Base::f(float)构成重载,
而Base::g(void)则被Derived::g(void)覆盖
#include <iostream.h>
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;}
};
Void 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)
}
提示:
1. Virtual 关键字告诉编译器,派生类中相同的成员函数应该放到vtable中,并且替换基类中相应成员函数的槽位;
2. 虚函数的覆盖有两种方式:完全重写和扩展。扩展是指派生类虚函数首先调用基类的虚函数,然后再增加新的功能;
2.令人迷惑的隐藏规则
本来仅仅区别重载与覆盖并不算困难,单丝C++的隐藏规则使问题的复杂性陡然增加。这里“隐藏”是指派生类的成员函数遮蔽了与其同名的基类成员,具体规则如下:
派生类的函数与基类的函数同名,但是参数列表有所差异。此时,不论有无virtual关键字,基类的成员函数在派生类中将被隐藏(注意别与重载混淆);
派生类的函数与基类的函数同名,参数列表也相同,但是基类函数没有virtual关键字,此时,基类的函数在派生类中将被隐藏(注意别于覆盖混淆)。
如下示例:
函数Derived::f(float)覆盖了Base::f(float)
函数Derived::g(int)隐藏了Base::g(float),而不是重载
函数Derived::h(folat)隐藏了Base::h(float),而不是覆盖
#include <iostream.h>
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}
}
Void main(void)
{
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(int)3
Pb->h(3.14f); //base::h(float) 3.14
Pd->h(3.14f); //derived::h(float)3.14
}
提示:
如果确实想使用基类的成员函数,可以在派生类定义中的任何地方显式的使用using关键字,如下:
Class derived: public base
{
Public:
Using Base::g;
Void g(int x) {……}
};
3. 摆脱隐藏
隐藏规则引起了不少麻烦,如下,程序员可能期望语句pd->f(10)调用函数base::f(int),但是base::f(int)不幸被derived::f(char *)隐藏了。由于数字10不能被隐式的转换为字符串类型所以在编译时出错。
Class base
{
Public:
Void f(int x);
};
Class derived : public base
{
Void f(char *str);
};
Void test(void)
{
Derived *pd = new derived;
Pd->f(10); //error ,此处在编译的时候出错。
}
有了隐藏规则,编译器将明确的指出错误;
假如派生类有多个基类(多重继承),有时搞不清楚哪些基类定义了函数f, 如果没有隐藏规则,那么pd->f(10)可能会调用一个出乎意料的基类函数f().
提示:
如果语句pd->f(10)确实想调用函数base::f(int),那么有两个方法:
1. 就是使用using声明;
Class derived : public base
{
Public:
Using Base::g;
Void g(int x){……}
}
2. 把类修改成如下的示例:
Class derived: public base
{
Public:
Void f(char *str);
Void f(int x) {base::f(x);}
};
- 高质量程序设计指南--重载 覆盖 隐藏
- 高质量c++(重载、覆盖、隐藏)
- 高质量c++(重载、覆盖、隐藏)
- 高质量c++(重载、覆盖、隐藏)
- 高质量c++(重载、覆盖、隐藏)
- 重载 覆盖 隐藏【c++ 高质量编程】
- 高质量c++(重载、覆盖、隐藏)
- 高质量c++(重载、覆盖、隐藏)
- 高质量C++成员函数的重载、覆盖与隐藏
- 高质量C++编程(函数重载,覆盖,隐藏)
- 高质量程序设计指南
- 高质量程序设计指南 读书笔记
- 高质量c++(重载、多态、隐藏)
- 高质量C++/C程序设计指南
- 高质量程序设计指南:C++/C语言
- 高质量程序设计指南-C++语言 笔记(1)
- 高质量程序设计指南-C++ 笔记(1)
- 高质量程序设计指南-C++ 笔记(2)
- 关于更改linux下系统资源限制:ulimit
- 基础函数的实现(strcpy,strcat, strcmp, atoi, itoa)
- Fedora8 安装VMware Tools全过程图解
- Java线程池
- 如何在beamer中添加其它语言的描述性源代码【方法一】
- 高质量程序设计指南--重载 覆盖 隐藏
- 无敌的数据结构题目(2)
- Android Design
- ORM软件清单
- VS2010 调试技巧
- 安装使用sqlserver2000数据库的一些问题及解决方案
- C++中 static、const 应用小结 .
- 关于在HMAC_MD5加密遇到的问题
- 总结2011