多态
2016-07-26 22:59
169 查看
1、内存模型
当定义一个子类对象时,该子类就会有相应的内存情况,此时就是内存模型;
2、虚函数
虚函数是一个类的成员函数,其定义格式如下:virtual 返回值类型 函数名(参数表);
关键字virtual指明该成员函数为虚函数。
(1)、必须在继承体系中;
(2)、父类中存在的成员函数为虚函数的(virtual);
(3)、子类必须达到三同(返回值 函数名 参数列表)
(4)、必须通过父类型的指针/引用来调用;
(5)、两个类外;
i:父类的成员函数返回值为 Base*
子类的成员函数返回值为 D* 此时,打破三同,仍为覆盖!!!
ii:父类的析构函数一般都要加上(virtual),就可以利用多态性级联的调用析构函数,此时
先调用子类的,在调用父类的;(以免发生内存泄漏)!!!
4、虚函数剖析
(1)、当在类中出现一个(virtual),虚方法时,对象中第一个成员将是:_vptr;
此时只有一个成员,应该为4B,但是其因为有虚函数的存在,内部的第一个成员就一定为虚表指针;
指针32位下为4字节,所以此时一共为8字节;(不管内部有多少个虚函数,但是虚表指针只有一个);
(2)、虚函数将在继承体系中,一直为虚(覆盖时); 此时的virtual可以省略不写;
(3)、多态:就是对虚方法的重写;
(4)、虚表:装虚函数的表,其本质是地址的覆盖;
5、多态的原理
这是没有覆盖的虚表:
假如子类有一个方法与父类的虚方法三同,此时覆盖;
但是通过父类的指针/引用永远只能访问父类对象的部分;
如何取得虚表中的函数呢?
父类均为虚函数,子类中也有虚函数,且没有进行覆盖,则将子类的放到第一个虚表的最后,其余的父类虚表就不用放了;因为,
就是放了,通过父类的指针/引用也访问不了,浪费内存空间;要是有覆盖的,则每个虚表都得画出;其余情况类似分析就行。
7、纯虚函数与抽象类
继承抽象类的,必须实现其所有方法,不然自己继承下来依旧是抽象类,不能实例化对象。
当定义一个子类对象时,该子类就会有相应的内存情况,此时就是内存模型;
2、虚函数
虚函数是一个类的成员函数,其定义格式如下:virtual 返回值类型 函数名(参数表);
关键字virtual指明该成员函数为虚函数。
class Test{ public: virtual void fun(){} //虚函数 };3、多态
(1)、必须在继承体系中;
(2)、父类中存在的成员函数为虚函数的(virtual);
(3)、子类必须达到三同(返回值 函数名 参数列表)
(4)、必须通过父类型的指针/引用来调用;
(5)、两个类外;
i:父类的成员函数返回值为 Base*
子类的成员函数返回值为 D* 此时,打破三同,仍为覆盖!!!
ii:父类的析构函数一般都要加上(virtual),就可以利用多态性级联的调用析构函数,此时
先调用子类的,在调用父类的;(以免发生内存泄漏)!!!
4、虚函数剖析
(1)、当在类中出现一个(virtual),虚方法时,对象中第一个成员将是:_vptr;
此时只有一个成员,应该为4B,但是其因为有虚函数的存在,内部的第一个成员就一定为虚表指针;
指针32位下为4字节,所以此时一共为8字节;(不管内部有多少个虚函数,但是虚表指针只有一个);
(2)、虚函数将在继承体系中,一直为虚(覆盖时); 此时的virtual可以省略不写;
(3)、多态:就是对虚方法的重写;
(4)、虚表:装虚函数的表,其本质是地址的覆盖;
5、多态的原理
这是没有覆盖的虚表:
假如子类有一个方法与父类的虚方法三同,此时覆盖;
但是通过父类的指针/引用永远只能访问父类对象的部分;
如何取得虚表中的函数呢?
Base b; cout<<&b<<endl; //对象的地址 printf("%p\n", *(int *)(&b)); //虚表中虚表指针的值(指针4字节),所以转换整形指针,也就是虚表指针的地址; ((Fun)*((int*)*(int*)(&b) + 0))(); //Fun是函数指针,将获得虚表中的第一个函数; ((Fun)*((int*)*(int*)(&b) + 1))(); //Fun是函数指针,将获得虚表中的第二个函数; ((Fun)*((int*)*(int*)(&b) + 2))(); //Fun是函数指针,将获得虚表中的第三个函数;6、多继承中虚表的画法
父类均为虚函数,子类中也有虚函数,且没有进行覆盖,则将子类的放到第一个虚表的最后,其余的父类虚表就不用放了;因为,
就是放了,通过父类的指针/引用也访问不了,浪费内存空间;要是有覆盖的,则每个虚表都得画出;其余情况类似分析就行。
7、纯虚函数与抽象类
#include<iostream> using namespace std; class Test{ public: virtual void fun() = 0; //这种形式就是存虚函数,赋值为0; virtual void fun1() = 0; virtual void fun2() = 0; virtual void fun3() = 0; }; int main(void){ return 0; }以上的类中都为纯虚函数的类叫做抽象类; 抽象类不能实例化;也就是不能定义对象;
继承抽象类的,必须实现其所有方法,不然自己继承下来依旧是抽象类,不能实例化对象。
相关文章推荐
- C#与.net高级编程 C#的多态介绍
- C#中面向对象编程机制之多态学习笔记
- C#中的多态深入理解
- C#中多态、重载、重写区别分析
- 设计引导--一个鸭子游戏引发的设计理念(多态,继承,抽象,接口,策略者模式)
- C++之普通成员函数、虚函数以及纯虚函数的区别与用法要点
- C++中虚函数与纯虚函数的用法
- C# 面向对象三大特性:封装、继承、多态
- javascript每日必学之多态
- c#基础学习之多态
- PHP面向对象三大特点学习(充分理解抽象、封装、继承、多态)
- 从汇编看c++中多态的应用
- javascript 面向对象全新理练之继承与多态
- Java多态的使用注意事项
- C#使用虚拟方法实现多态
- 实例讲解PHP面向对象之多态
- C#中多态现象和多态的实现方法
- 从汇编看c++中的多态详解
- C++基础之this指针与另一种“多态”
- 深入解析C++中的虚函数与多态