欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

C++ 虚拟指针(vptr)和虚拟表(虚拟函数表)(vtbl)|八月 更多挑战

最编程 2024-04-13 07:25:02
...

1、首先了解什么是虚函数

虚函数必须是类的非静态成员函数(且非构造函数),其访问权限是public(当然也可以定义为private or proteceted, 但是对于多态来说,没有意义。),在基类的类定义中定义虚函数的一般形式:

virtual 函数返回值类型 虚函数名(形参表){函数体}

简单点来说:就是在成员函数前加上virtual关键字。

1.1什么时候用虚函数?

对于设计者去设计成员函数来说:1、如果设计者不希望子类重新定义(覆写)某个成员函数,就把他设计成非虚函数(普通成员函数)。2、如果设计者希望子类重新定义(覆写)某个成员函数,且有默认定义,就把他设计成虚函数。3、如果设计者希望子类一定要重新定义(覆写)某个成员函数,且没有默认定义(当然纯虚函数也是可以有定义的),就把他设计成纯虚函数。

虚函数的注意事项:

1、基类析构函数必须定义为虚析构函数,因为如果基类析构函数不是虚析构函数,则delete一个派生类对象的基类指针会产生未定义的行为;

2、C++规定,当一个成员函数被声明为虚函数后,其派生类中的同名函数都自动成为虚函数。因此,在子类从新声明该虚函数时,可以加,也可以不加,但习惯上每一层声明函数时都加virtual,使程序更加清晰。

2、虚指针与虚表(虚函数表)

首先我们来看下图:

image-20210801140515129.png 从上表可以看出,每个实例对象都以一个自己特有的虚指针(在该类存在虚函数的情况下),而每个虚指针都指向一个虚表(虚函数表创建时机是在编译期间。编译期间编译器就为每个类确定好了对应的虚函数表里的内容。);子类和父类有同名虚函数,则在该类虚函数表里只存在子类虚函数地址。因此虚指针(和指针搭配使用)的具体工作方式如下:

如代码p->v3(),一个指针p指向C的示例对象c,p的指向的内存区域是虚指针地址,通过虚指针找到虚表(虚函数表),再找到相应的v3();

关于虚指针的注意事项:

1、假如即使一个类有100000个虚函数,那么他的虚指针也就一个,即不论有多少虚函数,虚指针都只有一个;

2、虚指针的大小在不同位电脑是不一样的,经测试在32位机上是4个字节,在64位机上是8个字节;

3、每个实例对象在有虚函数的情况下都有一个虚指针,虚指针指向每个实例对象的虚表,虚表里含有的指针指向可以调用的虚函数;

4、不论子类是实例例对象还是指针都可以通过与作用符号调用父类同名方法(函数),调用方法是c.B::A::v1()或p->B::A::v1(),这种行为``叫回避虚函数机制;

5、虚指针这种寻址函数的方式叫做动态绑定;

6、虚指针一般和父类指针搭配使用才有意义;

3、虚指针实现函数动态绑定后的强大功能

实现C++语言的多态性,举个最简单生活例子,看下图:

image-20210801150849228.png 这么多种面食都从父类面食中继承而来,他们都应该有一个方法(成员函数)——制作方法(显示制作方法的成员函数或者说制作该面食的成员函数);

假如现在我们需要去输出每一种食物的制作方法,假设我们从标准输入输入了1000种不同的面食(实例对象),我们不可能依次调用每种面食的制作方法,此时应该采用循环输出的方式,我们学过继承都知道,父类指针可以指向子类,因此我们仅需要在循环体内部,定义一个父类指针,将每种面食的地址传给该指针,在调用制作方法就可以完美输出每种食物的制作方法了。

上述过程体现了C++的多态性,也就是体现了面向对象三大特性之一的多态。

只就是本文的全部的内容了,觉不觉得有用都点个赞呗!!! ???? ???? ????