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;

}

###运行结果:
![](https://img2018.cnblogs.com/blog/1784621/201911/1784621-20191112185538732-616549306.png)

virtual void out()

{

cout << x << y << endl;

cout<<"A"<<endl;

}

输出内容和我们虚函数中写的函数需要我们输出的无异议。所以证明了我们之前的想法。
现在,对虚函数到底是怎么存在的应该没有什么问题了。

C++虚函数作用原理(一)——虚函数如何在C++语言逻辑中存在的更多相关文章

  1. 【C++】多态性(函数重载与虚函数)

    多态性就是同一符号或名字在不同情况下具有不同解释的现象.多态性有两种表现形式: 编译时多态性:同一对象收到相同的消息却产生不同的函数调用,一般通过函数重载来实现,在编译时就实现了绑定,属于静态绑定. ...

  2. c++ 虚函数和纯虚函数

    在你设计一个基类的时候,如果发现一个函数需要在派生类里有不同的表现,那么它就应该是虚的.从设计的角度讲,出现在基类中的虚函数是接口,出现在派生类中的虚函数是接口的具体实现.通过这样的方法,就可以将对象 ...

  3. C++ - 虚基类、虚函数与纯虚函数

    虚基类       在说明其作用前先看一段代码 class A{public:    int iValue;}; class B:public A{public:    void bPrintf(){ ...

  4. C++中不能声明为虚函数的有哪些函数

    常见的不不能声明为虚函数的有:普通函数(非成员函数):静态成员函数:内联成员函数:构造函数:友元函数. 1.为什么C++不支持普通函数为虚函数? 普通函数(非成员函数)只能被overload,不能被o ...

  5. TWinControl与TControl的覆盖函数(TWinControl对TControl的10个消息覆盖函数,17个覆盖函数,私有虚函数仍可多态)

    手工找出来,对比一下,有助于VCL框架的理解.----------------------------------------------------------------------------- ...

  6. C++学习笔记(十二):类继承、虚函数、纯虚函数、抽象类和嵌套类

    类继承 在C++类继承中,一个派生类可以从一个基类派生,也可以从多个基类派生. 从一个基类派生的继承称为单继承:从多个基类派生的继承称为多继承. //单继承的定义 class B:public A { ...

  7. C++ Primer--虚函数与纯虚函数的区别

    首先:强调一个概念 定义一个函数为虚函数,不代表函数为不被实现的函数. 定义他为虚函数是为了允许用基类的指针来调用子类的这个函数. 定义一个函数为纯虚函数,才代表函数没有被实现. 定义纯虚函数是为了实 ...

  8. C++ 虚函数与纯虚函数

    #include<iostream> #include<string> using namespace std; class A{ public: virtual void f ...

  9. c++中虚函数和纯虚函数定义

    只有用virtual声明类的成员函数,使之成为虚函数,不能将类外的普通函数声明为虚函数.因为虚函数的作用是允许在派生类中对基类的虚函数重新定义.所以虚函数只能用于类的继承层次结构中. 一个成员函数被声 ...

随机推荐

  1. Attention is all you need 详细解读

    自从Attention机制在提出之后,加入Attention的Seq2Seq模型在各个任务上都有了提升,所以现在的seq2seq模型指的都是结合rnn和attention的模型.传统的基于RNN的Se ...

  2. vscode setting.json (@vue/eslint-config-prettier)

    {     "workbench.colorTheme": "Default Light+", // 主题     "terminal.integra ...

  3. redis db0-15 的概念

    redis默认有db0~db15之多. redis有没有什么方法使不同的应用程序数据彼此分开同时又存储在相同的实例上呢?就相当于mysql数据库,不同的应用程序数据存储在不同的数据库下. redis下 ...

  4. 服务器:消息18456,级别16,状态1 用户‘sa’登录失败解决方法

    无法连接到服务器**:  服务器:消息18456,级别16,状态1   [Microsoft][ODBC   SQL   Server   Driver][Sql   server]   用户 'sa ...

  5. PHP中的闭包

    1.语句结构 在PHP中,由于存在函数内部不能访问全局作用的,所以就需要一种可以引入上一级作用域的语法结构,这种就是 function () use () {} 将需要引入到这个函数作用于内的变量写入 ...

  6. 【LOJ】#3090. 「BJOI2019」勘破神机

    LOJ#3090. 「BJOI2019」勘破神机 为了这题我去学习了一下BM算法.. 很容易发现这2的地方是\(F_{1} = 1,F_{2} = 2\)的斐波那契数列 3的地方是\(G_{1} = ...

  7. IDEA中便捷更新Git项目最新代码

    更新:IDEA中直接点击Gir后面的第一个图标 会出现一个这样的弹框,点击OK,就可以将GitLab中最新的代码更新到IDEA中(本地)

  8. 剑指offer10:2*1的小矩形横着或者竖着去覆盖2*n的大矩形,总共有多少种方法?

    1. 题目描述 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形.请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? 2.思路和方法 思路:(下面说到的x*y的矩形,x是宽 ...

  9. django ajax MTV与MVC 多对多创建方式

    MTV与MVC MTV模型(django): M:模型层(models.py) T:templates V:views MVC模型: M:模型层(models.py) V:视图层(views.py) ...

  10. Jmeter之cookie登录

    1.在web登录时,抓取登录的响应头 2.在jmeter中配置cookie HTTP Cookie管理器中添加信息 以下三个字段是必填的 3.添加HTTP请求(直接访问首页) 如果返回成功,并且响应内 ...