【C++学习手札】一文带你认识C++虚函数(内层剖析)

简介: 【C++学习手札】一文带你认识C++虚函数(内层剖析)

虚函数的概念

       C++面向对象中的多态性是指同一种类型的对象在不同的情况下表现出不同的行为。这种多态性可以通过虚函数来实现。在C++中,虚函数是指在基类中声明的函数,在派生类中可以被重写,从而实现不同的行为。当使用基类指针或引用调用虚函数时,实际调用的是派生类中重写的函数,而不是基类中的函数。 通过使用虚函数,可以实现运行时多态性,即在程序运行时才确定调用哪个函数,而不是在编译时确定。这种多态性可以提高程序的灵活性和可扩展性,使得程序更加易于维护和扩展。

     简而言之,就是用父类型别的指针指向其子类,然后通过父类的指针调用实际子类的成员函数。

   🌰

class Animal
   {
 public:
   void sleep(void)
     {
     cout << "animal 动物在睡觉" << endl;
     }
   };
 class Cat :public Animal
 {
 public:
   void sleep(void)
     {
     cout << "Cat 猫在睡觉!! 喵喵" << endl;
     }
   };
 void test01()
 {
   //用基类(指针或引用) 保存 子类对象(向上转换)
     Animal * p = new Cat;
   p-> sleep();//调用的是基类的sleep
     Cat cat;  Animal & ob = cat;
   ob.sleep();//调用的是基类的sleep
 }

  在这个例子中,我们想实现的功能是什么呢?我们用的是父类的指针指向了子类的空间,想要调用其中的成员函数,但是事实真的如我们所愿吗?请看以下运行结果:

        可以看到我们实际上调用的都是父类中的成员函数,而这也是C++继承在作祟。对此,我们使用虚函数!(仅仅只是加了一个 virtual)

class Animal
   {
 public:
   virtual void sleep(void)
     {
     cout << "animal 动物在睡觉" << endl;
     }
   };

运行结果又是如何呢?如下:

        这是什么原因呢?这就要提到虚函数的结构了!

虚函数的结构

       定义

virtual 函数(包涵返回值、参数等等(就是在前面多加了个virtual))

      内层结构(重要)

       我们使用Develop Command Prompt for VS 2022 打开相应的类结构,如下为加了virtual的父类Animal


 vfptr是虚函数指针 指向的是虚函数表(vftable)
 vftable表存放的是 vfptr做保存的函数入口地址

一图让你明白~

        当函数前加了virtual后会自动生成一个vfptr指针以及一个vftable,虚函数指针会指向这个虚函数表,而函数表中通常储存着虚函数入口的地址。而这些地址的存储也是有一定的规则的,他们通过序号以及当前的虚指针相对于虚基类的首地址的偏移量。当其中有多个虚函数时,以便找到相应的函数。

重要的来了,那为啥当我们在父类指针中定义了虚函数,而在子类中就能实现用父类指针就可以访问子类的成员函数了呢?

      这是因为:当虚函数涉及到继承的时候 子类 会继承 父类的(虚函数指针vfptr 虚函数表vftable),编译器会将虚函数表中的函数入口地址 更新 成子类的 同名(返回值、参数都同)的函数入口地址。如果基类指针、引用 访问虚函数的时候 就会 间接的调用 子类的虚函数。

二图让你明白~

       

看到这里,相信你的好奇心起来了,如何查找类的结构呢?别急~接下来就分享给你(*╹▽╹*)


如何查看类的内层结构

       1、首先在你的任务栏中搜索        Develop Command Prompt for VS 2022   (2022是版本,你可以根据自己的版本变更)

       2、打开后回到你的VS执行以下操作

        3、回到 Develop Command Prompt for VS 2022,输入以下命令

       如果你的文件是在E盘 你首先得先进入E盘 所以输入 E: 如果是C盘则C:以此类推

在进入所在盘后,进入到对应的路径 cd + 路径 如下:

       4、输入对应的操作  

       cl /d1 reportSingleClassLayout+类名 类所在程序名.cpp

        如下:


虚函数的应用案例

(基类指针、引用 作为函数的参数)

        🌰

#include <iostream>
using namespace std;
 class Base {
 public:
   virtual void sleep(void)
     {
     cout << "父亲在睡觉" << endl;
     }
};
 class Son1 :public Base
 {
 public:
   void sleep(void)
     {
     cout << "Son1在安静的睡觉" << endl;
     }
   };
 class Son2 :public Base
 {
 public:
   virtual void sleep(void)
     {
     cout << "Son2在轻度的睡觉" << endl;
     }
   };
 class Son3 :public Base
 {
 public:
   virtual void sleep(void)
     {
     cout << "Son3在雨声般的睡觉" << endl;
     }
   };
 class Son4 :public Base
 {
 public:
   virtual void sleep(void)
     {
     cout << "Son4在鼾声如雷" << endl;
     }
   }; 
   //以基类指针作为函数的参数 函数可以操作该基类派生出的任意子类对象
     void sleepFun(Base & ob)
     {
     ob.sleep();
     }
     int main(int argc, char* argv[])
     {
     Son1 ob1;
     Son2 ob2;
     Son3 ob3;
     Son4 ob4;
     sleepFun(ob1);
     sleepFun(ob2);
     sleepFun(ob3);
     sleepFun(ob4);
     return 0;
    }

  运行结果如下:


               感谢你耐心的看到这里ღ( ´・ᴗ・` )比心,如有哪里有错误请踢一脚作者o(╥﹏╥)o!  

相关文章
|
3月前
|
算法 C语言 C++
C++语言学习指南:从新手到高手,一文带你领略系统编程的巅峰技艺!
【8月更文挑战第22天】C++由Bjarne Stroustrup于1985年创立,凭借卓越性能与灵活性,在系统编程、游戏开发等领域占据重要地位。它继承了C语言的高效性,并引入面向对象编程,使代码更模块化易管理。C++支持基本语法如变量声明与控制结构;通过`iostream`库实现输入输出;利用类与对象实现面向对象编程;提供模板增强代码复用性;具备异常处理机制确保程序健壮性;C++11引入现代化特性简化编程;标准模板库(STL)支持高效编程;多线程支持利用多核优势。虽然学习曲线陡峭,但掌握后可开启高性能编程大门。随着新标准如C++20的发展,C++持续演进,提供更多开发可能性。
81 0
|
26天前
|
编译器 C语言 C++
配置C++的学习环境
【10月更文挑战第18天】如果想要学习C++语言,那就需要配置必要的环境和相关的软件,才可以帮助自己更好的掌握语法知识。 一、本地环境设置 如果您想要设置 C++ 语言环境,您需要确保电脑上有以下两款可用的软件,文本编辑器和 C++ 编译器。 二、文本编辑器 通过编辑器创建的文件通常称为源文件,源文件包含程序源代码。 C++ 程序的源文件通常使用扩展名 .cpp、.cp 或 .c。 在开始编程之前,请确保您有一个文本编辑器,且有足够的经验来编写一个计算机程序,然后把它保存在一个文件中,编译并执行它。 Visual Studio Code:虽然它是一个通用的文本编辑器,但它有很多插
|
1月前
|
Java 编译器 C++
c++学习,和友元函数
本文讨论了C++中的友元函数、继承规则、运算符重载以及内存管理的重要性,并提到了指针在C++中的强大功能和使用时需要注意的问题。
21 1
|
3月前
|
编译器 C++ 索引
C++虚拟成员-虚函数
C++虚拟成员-虚函数
|
4月前
|
存储 安全 编译器
【C++入门 四】学习C++内联函数 | auto关键字 | 基于范围的for循环(C++11) | 指针空值nullptr(C++11)
【C++入门 四】学习C++内联函数 | auto关键字 | 基于范围的for循环(C++11) | 指针空值nullptr(C++11)
|
4月前
|
人工智能 分布式计算 Java
【C++入门 一 】学习C++背景、开启C++奇妙之旅
【C++入门 一 】学习C++背景、开启C++奇妙之旅
|
4月前
|
存储 自然语言处理 编译器
【C++入门 三】学习C++缺省参数 | 函数重载 | 引用
【C++入门 三】学习C++缺省参数 | 函数重载 | 引用
|
4月前
|
小程序 C++
【C++入门 二 】学习使用C++命名空间及其展开
【C++入门 二 】学习使用C++命名空间及其展开
|
4月前
|
存储 C++ 索引
|
4月前
|
C++
C++基础知识(四:类的学习)
类指的就是对同一类对象,把所有的属性都封装起来,你也可以把类看成一个高级版的结构体。