C++虚函数作用原理(一)——虚函数如何在C++语言逻辑中存在
C++多态,接触其实也没太长的时间。上课的时候老师总是不停的讲,多态可以实现利用一个基类对象调用不同继承类的成员函数。我就会觉得很伤脑筋,这个的原理到底是什么?是什么呢?
开始的时候我觉得自己应该能够把它的原理想出来,因为一直觉得关于这些高级语言的事情,不论看起来多么神奇,其实应该都是之前学的基础累积起来的。所以,我就自己想了一段时间————能够实现这样效果的只有 指针 了。
但是这个指针应该怎么定义呢?就算基类中本身定义了一个指针,可是继承类中被继承来的函数在利用基类的时候怎么告诉基类到底调用哪一个继承类的函数呢?真的伤脑筋。
……
现在是开始这个博客的第二天,我终于可以开始继续写了——因为我开始自己调试观察虚函数。
OK,现在开始了:
首先:
一、没有继承的类
(1)段小小的代码:
class A
{
int x;
int y;
public:
virtual void out()
{
cout << x << y << endl;
cout<<"A"<<endl;
}
};
int main()
{
A a;
return 0;
}
十分明显这段程序中仅仅只有一个类,一个虚函数!现在我们一起来看看类A的成员到底如何分布的。

成员变量x和y存在。同时出现了 _vptr 。它是什么?没错儿就是虚函数表指针。也就是说这个_vptr就是指向虚函数表(或者理解它为指向,存有所有虚函数地址的一个数组的指针)的一个指针!
现在我们点开_vptr发现:

它里面仍然是一个指针但是这个是指向我们唯一的虚函数void out()的指针!
总结:
通过上面的观察,我们知道了虚函数是由虚函数表里面存储的地址通过寻址的方式来实现的。那么就意味着我们可以直接通过地址来调用函数!这里我们也可以通过一段代码验证我所述的是否为真。
首先我们要获得虚函数表指针:
int main()
{
A a;
int *_Avptr;
_Avptr = (int *)&a;//获得虚函数表指针,并通过强制转化为(int*)型。
return 0;
}

获得虚函数指针
int main()
{
A a;
int *_Avptr;
int *Varr;
_Avptr = (int *)&a;//获得虚函数表指针,并通过强制转化为int*型。
Varr = (int *)*(_Avptr);//获得虚函数指针。
return 0;
}

直接通过指针调用函数
```typedef void(*pFUNC)(void);//定义一个无返回值,无参数的指针型函数。
```
```
int main()
{
A a;
int *_Avptr;
int *Varr;
_Avptr = (int *)&a;//获得虚函数表指针,并通过强制转化为int型。
Varr = (int *)*(_Avptr);//获得虚函数指针。
pFUNC pfunc1 = (pFUNC)*Varr;//开始利用地址直接访问虚函数
pfunc1();
return 0;
}
###运行结果:

virtual void out()
{
cout << x << y << endl;
cout<<"A"<<endl;
}
输出内容和我们虚函数中写的函数需要我们输出的无异议。所以证明了我们之前的想法。
现在,对虚函数到底是怎么存在的应该没有什么问题了。
C++虚函数作用原理(一)——虚函数如何在C++语言逻辑中存在的更多相关文章
- 【C++】多态性(函数重载与虚函数)
多态性就是同一符号或名字在不同情况下具有不同解释的现象.多态性有两种表现形式: 编译时多态性:同一对象收到相同的消息却产生不同的函数调用,一般通过函数重载来实现,在编译时就实现了绑定,属于静态绑定. ...
- c++ 虚函数和纯虚函数
在你设计一个基类的时候,如果发现一个函数需要在派生类里有不同的表现,那么它就应该是虚的.从设计的角度讲,出现在基类中的虚函数是接口,出现在派生类中的虚函数是接口的具体实现.通过这样的方法,就可以将对象 ...
- C++ - 虚基类、虚函数与纯虚函数
虚基类 在说明其作用前先看一段代码 class A{public: int iValue;}; class B:public A{public: void bPrintf(){ ...
- C++中不能声明为虚函数的有哪些函数
常见的不不能声明为虚函数的有:普通函数(非成员函数):静态成员函数:内联成员函数:构造函数:友元函数. 1.为什么C++不支持普通函数为虚函数? 普通函数(非成员函数)只能被overload,不能被o ...
- TWinControl与TControl的覆盖函数(TWinControl对TControl的10个消息覆盖函数,17个覆盖函数,私有虚函数仍可多态)
手工找出来,对比一下,有助于VCL框架的理解.----------------------------------------------------------------------------- ...
- C++学习笔记(十二):类继承、虚函数、纯虚函数、抽象类和嵌套类
类继承 在C++类继承中,一个派生类可以从一个基类派生,也可以从多个基类派生. 从一个基类派生的继承称为单继承:从多个基类派生的继承称为多继承. //单继承的定义 class B:public A { ...
- C++ Primer--虚函数与纯虚函数的区别
首先:强调一个概念 定义一个函数为虚函数,不代表函数为不被实现的函数. 定义他为虚函数是为了允许用基类的指针来调用子类的这个函数. 定义一个函数为纯虚函数,才代表函数没有被实现. 定义纯虚函数是为了实 ...
- C++ 虚函数与纯虚函数
#include<iostream> #include<string> using namespace std; class A{ public: virtual void f ...
- c++中虚函数和纯虚函数定义
只有用virtual声明类的成员函数,使之成为虚函数,不能将类外的普通函数声明为虚函数.因为虚函数的作用是允许在派生类中对基类的虚函数重新定义.所以虚函数只能用于类的继承层次结构中. 一个成员函数被声 ...
随机推荐
- springboot-helloworld-eclipse
1.eclipse安装springboot插件 2.new->Spring Start ->group:组名称:artifact:组件名称:->选中web->finish 3. ...
- Chrome F12 谷歌开发者工具解析
一.工具简单介绍 F12可用于网站界面.性能测试,bug定位等 以 www.baidu.com 为例: Elements:查看页面元素属性(多用于自动化元素定位) Console:记录日志信息(用于定 ...
- 安装horizon
在控制节点上安装 controllerHost='controller' ADMIN_PASSWD='Ideal123!' 1.安装dashboard组件 yum -y install opensta ...
- Go语言入门篇-JSON&http调用
一.Decoder /(一)Decoder func DecoderExample(){ const jsonStream = ` { "Name" : "Ed" ...
- 【转帖】 解开龙芯与mips4000的关系
-- 苏联给的套件,我们只要把电子管插上就好. -- 千万次机器,不晓得来源 DJS-130系列,16位小型机,仿造美国NOVA DJS-180系列,超级小型机,仿造美国DEC VAX, 能跑DEC的 ...
- Linux切换root超级用户问题
具体方法如下: Ubuntu 1.使用终端工具的快捷键Ctrl + Alt +T 打开终端. 2.终端工具打开后如下图所示,操作就在这个窗口中进行 3.切换root用户的的方式一 执行命令 sudo ...
- Go语言Mac、Linux、Windows 下交叉编译
在很多时候,由于开发的方便,会有这样的场景出现,使用Mac开发或使用Windows开发,需要编译成Linux系统的执行文件,那么如何做到?Go语言提供了非常方便的命令行操作,即可实现. 1.Mac下编 ...
- ci框架读取上传的excel文件数据
原文链接: https://blog.csdn.net/qq_38148394/article/details/87921373 此功能实现使用到PHPExcel类库,PHPExcel是一个PHP类库 ...
- MySql常用字符集
常用字符集 位(bit):是计算机 内部数据 储存的最小单位,11001100是一个八位二进制数. 字节(byte):是计算机中 数据处理 的基本单位,习惯上用大写 B 来表示,1B(byte,字节) ...
- Python的IDE之Jupyter的使用
Python的IDE之Jupyter的使用 今天给大家分享的是Jupyter安装和基本使用教程,同时在我安装的过程中遇到了一些问题,解决方法,一并和大家分享 一.Jupyter介绍 Jupyter N ...