IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发工具 -> C++对象模型 --- 虚函数+虚基类+ 各种魔幻的组合,用最形象的描述,让你明白 -> 正文阅读

[开发工具]C++对象模型 --- 虚函数+虚基类+ 各种魔幻的组合,用最形象的描述,让你明白

大家好,我是 DongGu ,是一名软件工程专业大二的学生,写博客一方面是为了记录自己的学习过程,把自己犯的错误进行分享。但由于水平有限,博客中难免会有一些错误出现,有纰漏之处恳请各位大佬不吝赐教!有任何问题可以评论 或者 ___>
QQ联系(1521839703)
个人博客网站也搭好啦: dongguxy.top

1. 关于虚析构的认识

先看上面3种情况,其实设不设为虚函数都没问题, 就是怕delete一个动态分配的对象,且动态类型为子类的时候,会出现指针的静态类型与被删除对象的动态类型不符合的情况

  • 如果不为虚,会发生什么:

    1. 那么就会出现第三种情况,子类的析构函数不发生
    2. 普通函数都是静态绑定的,你这里的指针变量a是g类型,那么调用函数肯定是g里的方法
  • 为什么要让父类的析构函数要设成虚的, 主要有一下方面:

  1. 我们都知道, 有了虚函数,就有了虚函数表,有了虚函数表,就会继承父类的虚函数表的内容,如果子类没有重写父类的虚函数方法,那么该函数地址不会变化,如果写了,那么就会更新虚函数表的函数地址,
  2. 然后我们又想,如果父类实现虚析构函数,子类没有实现怎么办? 我们要记住,如果父类有虚函数,系统会给我们实现一个默认构造函数,默认析构函数,默认拷贝构造函数,后面会讲,
  3. 调用虚函数的时候,就会读到虚函数表的地址,再通过偏移量去调用,因为虚函数表的函数位置是不变的,函数地址在编译前就确定了的

测试代码

 #include<algorithm>
 #include<iostream>
 using namespace std;
 
 
 class Father {
 public:
 	int fa;
 	virtual ~Father(){}
 	virtual void i() {}
 };
 
 class Son:public Father{
 public:
 	int s;
 	virtual void i() {}
 	~Son() {}
 };
 
 int main() 
 {
 	Father* f = new Son;
 	f->i();
 	f->Father::i();
 	f->fa = 10;
 	delete f;
 	return 0;
 }

2. 虚函数

  • 多重继承下的虚函数,一图以蔽之

在这里插入图片描述

测试代码:

#include<algorithm>
#include<iostream>
using namespace std;

class Father {
public:
	int fa;
	virtual ~Father() { cout << "~Father\n"; }
	virtual void i() {}
};

class Father2 {
public:
	int fa2;
	virtual ~Father2() { cout << "~Father2\n"; }
	 virtual void j() {}
	 virtual void k() {}
};

class Son:public Father,public Father2{
public:
	int s;
	virtual void i() {}
	virtual void k() {}
	virtual ~Son() { cout << "~Son\n"; }
};

int main() 
{

	Son* s = new Son;
	s->k();

	Father* f = s;
	f->i();
	f->fa = 10;

	Father2* f2 = s;
	f2->j();
	f2->k();
	f2->fa2 = 2;

	delete f2;
	return 0;
}

3. 虚基类

  1. 虚继承父类,类中有虚函数

测试代码

#include<algorithm>
#include<iostream>
using namespace std;

class B {
public:
	int b;
};

class B1 :public virtual B {
public:
	int b1;
	virtual void fun() { cout << "B1 fun\n"; }
};

int main() {

	B1* b1 = new B1;
	b1->b1 = 10;
	b1->b = 3;
	b1->fun();
	return 0;
}
  1. 虚继承父类,父类有虚函数

    在这里插入图片描述

  1. 当一个类虚继承继承多个父类的时候

    在这里插入图片描述

测试代码

 
 #include<algorithm>
 #include<iostream>
 using namespace std;
 class B {
 public:
 	int b;
 };
 
 class B1 :public virtual B {
 public:
 	int b1;
 	virtual void fun() { cout << "B1 fun\n"; }
 };
 
 class B2 : public virtual B {
 public:
 	int b2;
 };
 
 class C {
 public:
 	int c;
 };
 
 class A :public B1, public B2, public C {
 public:
 	int a;
 };
 
 int main() {
 	A a;
 	a.b = 10;
 	a.b1 = 3;
 	a.b2 = 4;
 	a.c = 5;
 	a.a = 6;
 
 
 	B1* b1 = new A;
 	b1->b = 10;
 	b1->b1 = 20;
 	b1->fun();
 	return 0;
 }
  1. 多继承,都有虚函数时,就相当于,每个类中包含虚函数表,虚基类表,数据成员,如果子类有虚函数,那么该虚函数表和第一个父类共用一个虚函数表

在这里插入图片描述

测试代码如下:

#include<algorithm>
#include<iostream>
using namespace std;
class B {
public:
	int b;
};

class B1 :public virtual B {
public:
	int b1;
	virtual void fun() { cout << "B1 fun\n"; }
};

class B2 : public virtual B {
public:
	int b2;
	virtual void fun1() { cout << "B1 fun\n"; }
};

class C {
public:
	int c;
	virtual void func() { cout << "c fun\n"; }
};

class A :public B1, public B2, public C {
public:
	int a;
	virtual void funa() { cout << "a fun\n"; }
};

int main() {
	A *a = new A;
	a->b = 10;
	a->b1 = 3;
	a->b2 = 4;
	a->c = 5;
	a->a = 6;
	a->fun();
	a->fun1();
	a->func();
	a->funa();


	B1* b1 = new A;
	b1->b = 10;
	b1->b1 = 20;
	b1->fun();

	B2* b2 = new A;
	b2->b = 10;
	b2->b2 = 20;
	b2->fun1();
	return 0;
}

总结

虚函数怎么访问呢,虚基类怎么访问呢?
就是通过this指针移到该静态类型的首地址去,然后通过调用虚函数表,虚基类表取查找地址,再访问

  开发工具 最新文章
Postman接口测试之Mock快速入门
ASCII码空格替换查表_最全ASCII码对照表0-2
如何使用 ssh 建立 socks 代理
Typora配合PicGo阿里云图床配置
SoapUI、Jmeter、Postman三种接口测试工具的
github用相对路径显示图片_GitHub 中 readm
Windows编译g2o及其g2o viewer
解决jupyter notebook无法连接/ jupyter连接
Git恢复到之前版本
VScode常用快捷键
上一篇文章      下一篇文章      查看所有文章
加:2022-05-05 11:40:32  更:2022-05-05 11:44:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 4:03:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码