C++ 类的多态三(多态的原理--虚函数指针--子类虚函数指针初始化)
//多态的原理--虚函数指针--子类虚函数指针初始化
#include<iostream>
using namespace std; /*
多态的实现原理(有自己猜想部分) 基础知识:
类中的成员函数本质上是C语言中的全局函数,只是在全局函数的参数列表中多加了一个结构体指针参数 详解:
对于类中没有用virtual关键字修饰的成员函数,c++编译器在静态编译的时候,c++就会确定对象调用的全局函数
当类中声明虚函数时,c++编译器会在静态编译的时候为这个类生成一个虚函数表,
虚函数表是一个存储类成员函数指针的数据结构,
一个虚函数表只属于一个类
虚函数表是由编译器自动生成与维护的
virtual成员函数的地址会被c++编译器放入虚函数表中 在定义一个对象的时候即运行时或者说动态编译的时候(未调用构造函数之前)---Point p1; ,
那么c++编译器会为这个对象 隐式的 分配4个字节大小的内存, 这个内存里是一个 指针变量
此时这个指针变量还是为NULL,当执行函数的构造函数的时候 c++编译器会默认的为这个指针变量赋值
这个指针变量会指向该类的虚函数表 对于子类而言,子类的初始化比较特殊,必须先调用父类的构造函数,这时候这个隐藏的指针变量会被初始化为父类中虚函数表的地址
随后子类对象又会再次调用自身的构造函数 这个隐藏的指针变量又会再一次被赋值为 子类 对应的类的虚函数表的地址 说明1:
通过虚函数表指针VPTR调用重写函数是在程序运行时进行的,因此需要通过寻址操作才能确定真正应该调用的函数。
而普通成员函数是在编译时就确定了调用的函数。在效率上,虚函数的效率要低很多。
说明2:
出于效率考虑,没有必要将所有成员函数都声明为虚函数 */ class Point{
public:
Point(){
PrintA();
}
virtual void PrintA(){
cout << "1 我是第一个父类虚函数 我必将产生占据4个字节大小的函数指针a " << endl;
}
virtual void PrintB(){
cout << "2 我是第二个父类虚函数 我必将产生占据4个字节大小的函数指针b " << endl;
}
virtual void PrintC(){
cout << "3 我是第三个父类虚函数 我必将产生占据4个字节大小的函数指针c " << endl;
}
private:
int b;
}; class PointA :public Point{
public:
void PrintA(){
cout << "我是子类PointA 我重写了父类的虚函数 " << endl;
}
}; class PointB :public PointA{
void PrintA(){
cout << "我是孙子类 PointB 我重写了字类的重写函数 用来验证子类中的重写函数是不是一个虚函数 " << endl;
}
}; void ProtectA(PointA &pin){
pin.PrintA();
} void ProtectB(){
Point p1;
cout << "Point类型的大小" << sizeof(p1) << endl; //打印 8
//说明:c++编译器的确为虚函数分配了4个字节大小的内存 并且无论有多少个虚函数,只会分配4个字节大小的内存空间
//侧面证明了 虚函数指针指向的是一个虚函数表 而不是一个虚函数指针指向一个虚函数 PointA pa;
cout << "PointA类型的大小" << sizeof(pa) << endl; //打印 8
//根据结果说明:子类重写父类的虚函数,虽然没有加virtual关键字,但是本质上还是一个虚函数
//不然 为什么c++编译器为什么会为子类对象多分配4个字节大小的内存空间呢?
//做一下验证 写一个子类PointB 继承 PointA看是否能实现多态 PointB pb;
ProtectA(pb);// 打印出PointB 孙子类中的重写函数
//证明: 子类重写父类的虚函数,虽然没有加virtual关键字,但是本质上还是一个虚函数 } void ProtectC(){
//验证子类的分步初始化对虚函数指针的影响----我在父类的构造函数中调用一个虚函数,并且在子类中重写该虚函数
PointA pa;//调用了父类的PrintA()函数
//验证我文章开头结论
pa.PrintB(); } void main(){
ProtectC();
system("pause");
}

C++ 类的多态三(多态的原理--虚函数指针--子类虚函数指针初始化)的更多相关文章
- C++多态的实现及原理详细解析
C++多态的实现及原理详细解析 作者: 字体:[增加 减小] 类型:转载 C++的多态性用一句话概括就是:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型 ...
- day 25-1 接口类、抽象类、多态
# 接口类:python 原生不支持# 抽象类:python 原生支持的 接口类 首先我们来看一个支付接口的简单例子 from abc import abstractmethod,ABCMeta #我 ...
- 【C++】 多态的实现和原理
本文转自 https://www.cnblogs.com/cxq0017/p/6074247.html 安利一篇blog,https://blog.csdn.net/u013982161/articl ...
- Python进阶(十六)----面向对象之~封装,多态,鸭子模型,super原理(单继承原理,多继承原理)
Python进阶(十六)----面向对象之~封装,多态,鸭子模型,super原理(单继承原理,多继承原理) 一丶封装 , 多态 封装: 将一些东西封装到一个地方,你还可以取出来( ...
- 深入理解OOP(三):多态和继承(动态绑定和运行时多态)
在前面的文章中,我们介绍了编译期多态.params关键字.实例化.base关键字等.本节我们来关注另外一种多态:运行时多态, 运行时多态也叫迟绑定. 深入理解OOP(一):多态和继承(初期绑定和编译时 ...
- Java三大特征之多态(三)
面向对象编程有三大特性:封装.继承.多态. 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据.对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法. 继承 ...
- 【JAVA零基础入门系列】Day13 Java类的继承与多态
继承是类的一个很重要的特性,什么?你连继承都不知道?你是想气死爸爸好继承爸爸的遗产吗?(滑稽) 开个玩笑,这里的继承跟我们现实生活的中继承还是有很大区别的,一个类可以继承另一个类,继承的内容包括属性跟 ...
- C++ 多态的实现及原理
C++的多态性用一句话概括就是:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数.如果对象类型是派生类,就调用派生类的函数:如果对象类型是基类 ...
- 【游戏开发】在Lua中实现面向对象特性——模拟类、继承、多态
一.简介 Lua是一门非常强大.非常灵活的脚本语言,自它从发明以来,无数的游戏使用了Lua作为开发语言.但是作为一款脚本语言,Lua也有着自己的不足,那就是它本身并没有提供面向对象的特性,而游戏开发是 ...
随机推荐
- json字符串 与 json对象 的相互转换
var obj=JSON.parse(jsonstr); // 将json字符串转换成json对象 var str=JSON.stringify(jsonobj); // 将json对象转换成json ...
- HTML5 移动端如何使用css让百分比布局的弹窗水平和垂直方向上居中
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 《Linux内核设计与实现》笔记-1-linux内核简单介绍
一.Linux内核相对于传统的UNIX内核的比較: (1):Linux支持动态内核模块. 虽然Linux内核也是总体式结构,但是同意在须要的时候动态哦卸除(rmmod xxx)和载入内核模块(insm ...
- 使用Loadrunner进行文件的上传和下载
最近使用loadrunner中需要录制文件的上传和下载,上传功能模块利用录制可以直接实现,下载无法实现,在网上找到了一段代码,自己动手试验了下,发现没有用 辛苦找到的,还是记录下吧 (1)LoadRu ...
- Vue实例初始化的选项配置对象详解
Vue实例初始化的选项配置对象详解 1. Vue实例的的data对象 介绍 Vue的实例的数据对象data 我们已经用了很多了,数据绑定离不开data里面的数据.也是Vue的核心属性. 它是Vue绑定 ...
- View设置宽高
public class ViewMeasuare extends View { public ViewMeasuare(Context context, AttributeSet attrs) { ...
- android 总结
两点说明: 1. 本文我的老大推荐给的, 我自己之前也写过自学的帖子, 现在看看感觉不是很完整, 故转载此篇 2. 本文最后附有<android讲义 第二版> 下载地址, 我个人认为最适 ...
- jboss 的debug启动4法
http://xo-tobacoo.iteye.com/blog/684946方式一: 使用myeclipse,全自动化,不再赘述 方式二: eclipse下使用server工具,部署后使用debug ...
- Python selenium -- cookie处理
转自:http://www.cnblogs.com/fnng/p/3269450.html 本节重点: driver.get_cookies() 获得cookie信息 add_cookie(cooki ...
- Java程序猿的JavaScript学习笔记(10—— jQuery-在“类”层面扩展)
计划按例如以下顺序完毕这篇笔记: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScript ...