栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

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

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

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

1. 关于虚析构的认识

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

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

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

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

测试代码:

 #include
 #include
 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
#include
using namespace std;

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

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

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

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
#include
using namespace std;

class B {
public:
	int b;
};

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

int main() {

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

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

测试代码

 
 #include
 #include
 using namespace std;
 class B {
 public:
 	int b;
 };
 
 class B1 :public virtual B {
 public:
 	int b1;
 	virtual void fun() { cout << "B1 funn"; }
 };
 
 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
#include
using namespace std;
class B {
public:
	int b;
};

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

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

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

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

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指针移到该静态类型的首地址去,然后通过调用虚函数表,虚基类表取查找地址,再访问

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/847098.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号