C++复习要点总结之十——多态(一)
是一个面向对象新需求:
根据实际的对象类型来判断重写函数的调用
如果父类指针指向的是父类对象则调用父类中定义的函数
如果父类指针指向的是子类对象则调用子类中定义的重写函数
解决方案:
Ø C++中通过virtual关键字对多态进行支持
Ø 使用virtual声明的函数被重写后即可展现多态特性
//面向对象3大概念
封装
突破了C语言函数的概念。。
继承
代码复用 。。。。我复用原来写好的代码。。。
多态
多态可以使用未来。。。。。80年代写了一个框架。。。。。。90年代人写的代码
多态是我们软件行业追寻的一个目标。。。
//写了一个框架,可以调用后来人,写的代码的能力
进一步的理解
//间接赋值成立的3个条件:
//1 定义两个变量。。。
//2 建立关联 。。。。
//3 *p
//多态成立的三个条件:
//1 要有继承
//2 要有函数重写。。。C 虚函数
//3 要有父类指针(父类引用)指向子类对象
//多态是设计模式的基础,多态是框架的基础
知识点1 虚析构函数
析构函数是为了释放资源,
当释放资源时有需求不能直接对对象释放时如:
C *myC = new C; //C继承B,B继承A类
delete myC; //直接通过子类对象释放资源 这种情况不需要写virtual 关键字
需要通过父类指针将所有的子类都对象的析构函数都执行一遍
想通过父类指针 释放所有的子类资源 (需要在最终父类的析构函数中加上virtual关键字)
void howtodelete(A *base) { delete base; //这句话不会表现成多态 这种属性 }
知识点2:重载和重写区别
函数重载
必须在同一个类中进行
子类无法重载父类的函数,父类同名函数将被名称覆盖(例如:父类中有函数a(),子类中也有函数a(),但是还有函数a(int b)这个函数就是重载父类函数产生错误!不能出现!)
重载是在编译期间根据参数类型和个数决定函数调用
函数重写
必须发生于父类与子类之间
并且父类与子类中的函数必须有完全相同的原型
使用virtual声明之后能够产生多态(如果不使用virtual,那叫重定义)
多态是在运行期间根据具体对象的类型决定函数调用
例子分析:
//1 C++编译器 看到func名字 ,因子类中func名字已经存在了(名称覆盖).所以c++编译器不会去找父类的4个参数的func函数 //2 c++编译器只会在子类中,查找func函数,找到了两个func,一个是2个参数的,一个是3个参数的. //3 C++编译器开始报错..... error C2661: “Child::func”: 没有重载函数接受 4 个参数 //4 若想调用父类的func,只能加上父类的域名..这样去调用.. c1.func(1, 3, 4, 5); //c1.func(); //func函数的名字,在子类中发生了名称覆盖;子类的函数的名字,占用了父类的函数的名字的位置 //因为子类中已经有了func名字的重载形式。。。。 //编译器开始在子类中找func函数。。。。但是没有0个参数的func函数
3 重点:
C++中多态的实现原理
当类中声明虚函数时,编译器会在类中生成一个虚函数表
虚函数表是一个存储类成员函数指针的数据结构
虚函数表是由编译器自动生成与维护的
virtual成员函数会被编译器放入虚函数表中
存在虚函数时,每个对象中都有一个指向虚函数表的指针(vptr指针)
说明1:
通过虚函数表指针VPTR调用重写函数是在程序运行时进行的,因此需要通过寻址操作才能确定真正应该调用的函数。而普通成员函数是在编译时就确定了调用的函数。在效率上,虚函数的效率要低很多。
说明2:
出于效率考虑,没有必要将所有成员函数都声明为虚函数
说明3 :C++编译器,执行HowToPrint函数,不需要区分是子类对象还是父类对象
以上就是C++复习要点总结之十——多态(一)的内容,更多相关内容请关注PHP中文网(www.php.cn)!
上一篇: 基于PHP+Jquery制作的可编辑的表格的代码_jquery
下一篇: CSS3边框