深度理解派生与多态
来源:互联网 发布:交换机的数据帖转发式 编辑:程序博客网 时间:2024/05/22 02:05
利用C++进行编程都了解,面向对象编程基于三个基本的概念:数据抽象、继承和动态绑定。在C++中,用类进行数据抽象,用类派生从一个类继承另外一个:派生类继承基类的成员。动态绑定使编译器能够在运行时决定是使用基类定义的函数还是派生类中定义的函数。
许多应用程序的特性可以用一些相关但略有不同的概念来描述。例如,书店可以用不同的书提供不同的定价策略,有些书只能按照给定价格出售,另一些书可以根据折扣策略出售。
面向对象编程(object-oriented programming,oop)与这种应用非常匹配。通过集成可以定义一些类型,以模拟不同种类的书,通过动态绑定编写程序,来实现这其中的差异!
1. 概述
面向对象编程的关键思想是多态性(polymorphism)。
继承是指通过继承我们能够定义这样的类,他们对类型之间的关系建模,共享公共的东西,仅仅特化本质上不同的东西。派生类(derived class)能够继承基类(base class)定义的成员,派生类可以无须改变而是用那些与派生类型具体特性不相关的操作,派生类可以无需改变而使用那些与派生类型具体特性不相关的操作,派生类可以重定义那些与派生类型相关的成员函数,将函数特化。
实例:
#include <iostream>#include <string>using namespace std;class Item_Based{public: Item_Based(const string &book,double sale_price){ isbn = book; price = sale_price; }string book () const { return isbn; }virtual double net_price(size_t n) const //???? the function of "const"{ return n * price; }private:string isbn;protected: double price;};class Bulk_Item: public Item_Based{public:Bulk_Item(const string &book ,double sale_price, size_t qty,double dscnt) :Item_Based(book,sale_price) //Based class Initialized{min_qty = qty; discount = dscnt;}virtual double net_price(size_t ) const; //?????????private:size_t min_qty; // minimum purchase for discount to applydouble discount; // fractional discount to apply};inline double Bulk_Item::net_price(size_t cnt) const{if (cnt >= min_qty){return (1-discount)*price*cnt;} else{return price*cnt;}}void print_total(ostream &os,Item_Based &item, size_t n){os << "ISBN: ";os << item.book(); //operate overloados << "\tnumber sold: " ;os << n << "\ttotal price: ";os << item.net_price(n);os <<endl;//why the part didn't do derived net_price}int main(){Item_Based base("DaoMuBiJi",30);Bulk_Item derived("LaoJiuMen",30,2,0.5);// print_total makes a virtual call to net_priceprint_total(cout,base,10); // calls Item_base::net_priceprint_total(cout,derived,10); // calls Bulk_item::net_price}程序运行结果:
说明:1.虽然外接函数的第二个参数是Item_Base的引用,但是我们可以将Item_Base对象或者Bulk_Item对象传给它
2.因为形参是引用且net_price是虚函数,所以对net_price的调用将在运行时确定。调用哪个版本的net_price将在运行时确定!调用哪个版本net_price将依赖于传给print_tatal的实参!如果传给print_total的实参是Bulk_Item对像,将运行Bluk_Item中定义的应用折扣net_price;如果实参是一个Item_Base对象,则调用Item_Base定义的版本。
核心:在C++中,通过基类的引用或指针调用虚函数时,将发生动态绑定。引用(或指针)即可以指向基类对象也可以指向派生类对象,这一个事实是动态绑定的关键!!!用引用或指针调用的虚函数在运行时确定。(需要强调一点的是:基类的虚函数与派生类的虚函数定义必须一模一样。。。由于在派生类中,我丢掉了const标识符,导致我一度的怀疑,动态绑定的可行性)
2.访问情况
在基类中,public 和 private 标号具有普通含义:用户代码可以访问类的public 成员而不能访问 private 成员,private 成员只能由基类的成员和友元访问。派生类对基类的 public 和 private 成员的访问权限与程序中任意其他部分一样:它可以访问 public 成员而不能访问 private 成员。
这里需要强调一点的是protected(受保护的访问标号)。protected成员可以被派生类对象访问,但不能被该类型的普通用户访问。
可以认为 protected 访问标号是 private 和 public 的混合:
• 像 private 成员一样,protected 成员不能被类的用户访问。
• 像 public 成员一样,protected 成员可被该类的派生类访问。
• 像 private 成员一样,protected 成员不能被类的用户访问。
• 像 public 成员一样,protected 成员可被该类的派生类访问。
需要再次强调的是:一旦函数在基类中声明为虚函数,他就一直为虚函数,派生类无法改变该函数为虚函数这一事实,派生类重定义虚函数时,可以用virtual保留字,但是不是必须这样做!
3.virtual与其他成员函数
C++ 中的函数调用默认不使用动态绑定。要触发动态绑定,满足两个条件:第一,只有指定为虚函数的成员函数才能进行动态绑定,成员函数默认为非虚函数,非虚函数不进行动态绑定;第二,必须通过基类类型的引用或指针进行函数调用。 0 0
- 深度理解派生与多态
- 多态继承与派生
- 理解C++基类与派生类
- 继承与派生——多继承
- void与void 指针深度理解
- hive深度理解与调优
- 谈深度学习:“知道” 与 “理解”
- 图像通道与深度的理解
- 【深度学习与Theano】LSTM理解
- Unity Coroutine的深度理解与实践
- 深度理解C字符串与C++字符串
- Unity Coroutine的深度理解与实践
- Git流程理解与深度解析
- 继承派生多态(转东转西)
- C++ 继承派生多态
- 【C++的探索路11】继承与派生之拓展篇--多形式派生以及派生类指针转换
- 深度学习深理解(四)-深度网络与深度学习第一部分完结
- 派生类与继承
- mysql修改数据库字符集使支持中文输入
- iOS 堆和栈
- Git+GitHub,构建自己的开源仓库之踩坑
- Android Activity启动模式singleTask
- 5-26 Windows消息队列
- 深度理解派生与多态
- XML文件添加自动提示功能以及java文件中注释自动提示
- Spring数据源配置之Hibernate
- windows虚拟内存管理
- POJ 3177&&3352题解 tarjan算割边 求双连通分量 缩点
- C/C++面试必备(三)
- nil NULL Nil NSNull 区别
- 五子棋
- HDOJ 1872 稳定排序