二十二 多态(Polymorphic)
函数重写(虚函数覆盖)、多态概念
如果将基类中的某个成员函数声明为虚函数,那么子类与其具有相同原型的成员函数就也将是虚函数,并且对基类中的版本形成覆盖。
这时,通过指向子类对象的基类指针,或者引用子类对象的基类引用,调用该虚函数,实际被执行的将是子类中覆盖版本,而不是基类中的原始版本,这种语法现象称为多态.
eg:
class Base{
public:
virtual void foo(void){
cout << "Base::foo" << endl;
}
};
class Derived:public Base{
public:
void foo(void){
cout << "Derived::foo" << endl;
}
};
int main(void){
Derived d;
Base* pb=&d;//pb指向子类对象的基类指针
Base& rb=d;//rb引用子类对象的基类引用
pb->foo();//Derived::foo
rb->foo();//Derived::foo
} 函数重写要求(虚函数覆盖条件)
)类中普通的成员函数可以声明为虚函数,而全局函数、类中的静态成员函数、构造函数都不能声明为虚函数。
注:析构函数可以为虚函数(后面讲)
)只有在基类中以virtual关键字修饰的函数,才能作为虚函数被子类覆盖,而与子类中virtual关键字无关。
)虚函数在子类中的覆盖版本和改函数在基类中原始版本要拥有相同的函数签名,即函数名、形参表、常属性必须严格一致.
)如果基类中的虚函数返回基本类型的数据,那么子类的覆盖版本必须返回相同的类型。
)如果基类的虚函数返回类类型指针(A*)或引用(A&),那么允许子类返回其子类的指针(B*)或引用(B&)。--类型协变
class A{};
class B:public A{}; 多态的条件
)在满足虚函数覆盖前提下,必须要通过指针或引用调用该虚函数,才能表现出来。
)调用虚函数的指针也可以是this指针,只要它是一个指针子类对象的基类指针,调用虚函数时,同样可以表现多态的特性。//重点掌握 纯虚函数、抽象类和纯抽象类
)纯虚函数
virtual 返回类型 函数名(形参表)[const]=;
)抽象类
如果一个类中包含纯虚函数,那么这个类就是抽象类,抽象类不能创建对象。
)纯抽象类(有名接口类)
如果一个抽象类除了构造函数和析构函数以外的所有成员函数都是纯虚函数,那么该类就是纯抽象类。 注:如果子类没有覆盖抽象基类的纯虚函数,那么该子类就也是一个抽象类,类的抽象属性可以被继承. eg:PDF文档阅读器 多态实现原理(了解)
通过虚函数表和动态绑定,参考poly.jpg

)动态绑定会增加内存开销
)虚函数调用会增加时间开销
)虚函数不能被内联优化
结论:如果没有多态的语法要求,最好不要使用虚函数。 虚析构函数
)基类析构函数不能调用子类的析构函数,对一个指向子类对象的基类指针使用delete运算符,实际被执行的仅是基类的析构函数,所释放的仅是基类子对象构造时的分配的动态资源,而子类特有的动态资源将会形成内存泄露。
)将基类的析构函数声明为虚函数,那么子类的析构函数就也是一个虚函数,并且可以对基类的虚析构函数形成有效的覆盖,可以表现多态的特性。
)这时delete一个指向子类对象的基类指针,实际被调用的将是子类的析构函数,而子类的析构函数在执行后又会自动调用基类的析构函数,避免内存泄露。
//笔试题:虚析构函数的作用?
=========================================
练习:薪资计算
员工
/ | \
技术员 经理 销售员
\ / \ /
技术主管 销售主管
所有员工:姓名、工号、职位等级、出勤率
经理:绩效奖金(元/月)
技术员:研发津贴(元/小时)
销售员:提成比率(x%) 薪资=基本工资+绩效工资
基本工资计算=职位等级的固定额度*出勤率(输入);
绩效工资根据具体的职位而定:
普通员工:基本工资一半
经理:绩效奖金*绩效因数(输入)
技术员:研发津贴*工作小时数*进度因数(输入)
销售员:提成比率*销售额度(输入) 技术主管:(技术员绩效工资+经理绩效工资)/
销售主管:(销售员绩效工资+经理绩效工资)/ 结果:打印员工信息,输入必要数,计算和打印工资
class 员工{
double 计算工资(){
return 基本工资() + 绩效工资();
}
virutal void 绩效工资(){}
};
class 技术员:public 员工{
void 绩效工资(){}
}
int main(){
员工对象.计算工资();
技术员对象.计算工资();
}

最新文章

  1. SQLCMD备忘录:执行文件夹所有Sql文件
  2. Snap.svg – 现代 Web 开发必备的 JavaScript SVG 库
  3. jq获取当前点击的li是ul中的第几个?
  4. linux-5重要进程守护
  5. iOS 上拉刷新和下拉加在更多(第三方框架EGOTableViewPullRefresh)
  6. selenium实例
  7. CI 目录下放置index.html,防止直接访问
  8. Salted Password Hashing
  9. 【转】【公司调查】车来了APP
  10. 【转】iOS开发UITableViewCell的选中时的颜色设置
  11. 第二百三十九天 how can I 坚持
  12. SQL技术内幕四
  13. 调用数据库过程函数mysql
  14. Chrome下的语音控制框架MyVoix.js使用篇(三)
  15. oracle数据库删除数据Delete语句和Truncate语句的对比
  16. python3 int(整型)
  17. [LeetCode] Search in a Sorted Array of Unknown Size 在未知大小的有序数组中搜索
  18. 编译安装Python3
  19. vb.net WIN32API 获取listview的值
  20. 2019/3/2周末 java集合学习(一)

热门文章

  1. Android学习之6.0系统执行时权限设置
  2. [Python]通过websocket与jsclient通信
  3. windows脚本(VBS)之cmd命令行的妙用
  4. FZU 1894 志愿者选拔【单调队列】【monotone decreasing queue】
  5. QQ是怎样实现好友桌面快捷方式的?
  6. 《Effective C++ 》学习笔记——条款12
  7. bzoj3047:Freda的传呼机&amp;&amp;bzoj2125: 最短路
  8. codevs1060 搞笑世界杯(概率dp)
  9. Django day08 多表操作 (三) 基于对象的跨表查询 基于双下划线的多表查询
  10. Unity5.3.6升级到Unity5.4.4 NGUI出现Ignoring menu item NGUI because it is in no submenu!问题解决方案