C++中多态的原理【精华】

编程入门 行业动态 更新时间:2024-10-17 19:22:29

C++中多态的<a href=https://www.elefans.com/category/jswz/34/1770123.html style=原理【精华】"/>

C++中多态的原理【精华】

虚函数表

通过一道题我们先感受一下编译器针对多态的处理

#include <iostream>
using namespace std;class Base
{
public:virtual void Func1(){cout << "Func1()" << endl;}
private:int _b = 1;char _c
};int main()
{cout << sizeof(Base) << endl;return 0;
}

在x64环境下,显示的结果是12字节

为什么是12字节呢?一个int就4字节,一个char就1字节,内存对齐一下也是8字节呀!为什么显示的结果是12字节呢? 我们调试代码,看看内部结构

通过调试我们发现Base创建的对象里面有一个指针_vfptr,如果我们计算sizeof的时候把这个指针算上的话刚刚好的12字节!

那么疑问来了,这个指针到底是什么?为什么会出现在对象里面?这个指针到底有什么作用?

这个指针我们叫做虚函数表指针(v代表virtual,f代表function)。一个含有虚函数的类中都至少都有一个虚函数表指针,因为虚函数的地址要被放到虚函数表中,虚函数表也简称虚表,。那么子类中这个表放了些什么呢?我们接着往下分析

#include <iostream>
using namespace std;class Base
{
public:virtual void Func1(){cout << "Func1()" << endl;}virtual void Func2(){cout << "Func2()" << endl;}void Func3(){cout << "Func3()" << endl;}
private:int _b = 1;char _c;
};int main()
{cout << sizeof(Base) << endl;Base b;return 0;
}

通过监视窗口再来看:

我们发现这个指针指向一个数组(虚函数表),这个数组(表)里面存的就是虚函数的地址


知道了包含虚函数的类里面会出现一个指针,这个指针指向一个指针数组,数组里面保存的是类里面的虚函数,接下来我们看看多态的原理

文章目录

  • 虚函数表
  • 多态的原理


多态的原理

提示:这里可以添加本文要记录的大概内容:

class Person {
public:virtual void BuyTicket() { cout << "买票-全价" << endl; }virtual void func(){}
private:int _a = 1; 
};class Student : public Person {
public:virtual void BuyTicket() { cout << "买票-半价" << endl; }
private:int _b = 0; 
};void Func(Person& p)
{p.BuyTicket();
}int main()
{Person p;Student s;Func(p);Func(s);return 0;
}

我们看一下父类的虚表指针

我们看到Person对象里面的_vfptr指向的指针数组里面有两个指针,说明保存的是两个地址,我们看看这两个地址是什么?

然后我们看一下_vfptr指针指向的数组里面保存的地址

再看一下子类的虚表指针

虚函数需要被重写,一开始子类会将虚函数进行直接拷贝,重写虚函数之后,虚函数的地址就发生改变了

那为什么多态的原理和指向的对象有关?和虚表有什么关系?

父类对象找到虚函数表的地址,在表里面找到虚函数的地址,因为这里是父类对象,直接调用父类对象的虚函数
子类对象赋值给父类对象,这样会产生“切片”,找到子类中父类的那一部分,寻找到虚函数表的地址,但是虚函数表里存的是子类重写的父类虚函数的地址,所以此时_vfptr指向的其实是子类的虚函数指针数组,自认而然掉用的是子类的虚函数

那为什么不使用指针和引用后,就不构成多态了呢?

#include <iostream>
#include <string>
#include <vector>
using namespace std;class Person {
public:virtual void BuyTicket() { cout << "买票-全价" << endl; }virtual void func() {}
private:int _a = 1;
};class Student : public Person {
public:virtual void BuyTicket() { cout << "买票-半价" << endl; }
private:int _b = 0;
};void Func(Person p)
{p.BuyTicket();
}int main()
{Person p;Student s;Func(p);Func(s);return 0;
}

因为指针和引用是指向子类对象切割出来的父类对象的那一部分
不使用指针和引用后,直接将子类传递给父类,切割出来的子类对象中父类的那一部分,成员拷贝给父类,但是不会拷贝虚表指针

更多推荐

C++中多态的原理【精华】

本文发布于:2023-12-07 09:38:09,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1670865.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:原理   精华   多态

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!