C++类模型漫谈(四)

系统基于32位,MSVC编译器,VS开发工具

1、之前看到的都是简单一点的类型继承,现在看下另外一个例子,菱形继承(又称钻石继承)。一个TypeA基类,TypeB和TypeC继承TypeA,TypeD同时继承TypeB和TypeC。

class TypeA {
public:
	char a1 = 10;
	int a2 = 20;
	void virtual TypeA_Method1() {
		cout << "TypeA::TypeA_Method1" << endl;
	}
	void virtual TypeA_Method2() {
		cout << "TypeA::TypeA_Method2" << endl;
	}
};
class TypeB:public TypeA {
public:
	char b1 = 30;
	int b2 = 40;	
	void virtual TypeA_Method1() {//重写了TypeA中的TypeA_Method1
		cout << "TypeB::TypeA_Method1" << endl;
	}
	void virtual TypeB_Method1() {//TypeB类型自己的函数TypeB_Method1
		cout << "TypeB::TypeB_Method1" << endl;
	}
};
class TypeC:public TypeA {
public:
	char c1 = 50;
	int c2 = 60;
	void virtual TypeA_Method2() {//重写了TypeA中的TypeA_Method2
		cout << "TypeC::TypeA_Method2" << endl;
	}
	void virtual TypeC_Method1() {//TypeC类型自己的函数TypeC_Method1
		cout << "TypeC::TypeC_Method1" << endl;
	}
	void virtual TypeC_Method2() {//TypeC类型自己的函数TypeC_Method2
		cout << "TypeC::TypeC_Method2" << endl;
	}
};
class TypeD :public TypeB, public TypeC {
public:
	char c1 = 70;
	int c2 = 80;
	void virtual TypeA_Method1() {//重写了TypeA中的TypeA_Method1
		cout << "TypeD::TypeA_Method1" << endl;
	}
	void virtual TypeB_Method1() {//重写了TypeB中的TypeB_Method1
		cout << "TypeD::TypeB_Method1" << endl;
	}
	void virtual TypeC_Method1() {//重写了TypeC中的TypeC_Method1
		cout << "TypeD::TypeC_Method1" << endl;
	}
	void virtual TypeD_Method1() {//TypeD自己的函数TypeD_Method1
		cout << "TypeD::TypeD_Method1" << endl;
	}
};
int main()
{   
	TypeD  d_obj;

	//获取d_obj指针
	TypeD*  d_ptr = &d_obj;

	//d_ptr转换成其内部的TypeB子对象指针
	TypeB* b_ptr = d_ptr;

	//d_ptr转换成其内部的TypeC子对象指针
	TypeC* c_ptr = d_ptr;

	//d_ptr内存中有两个TypeA子对象,无法确定转到哪个TypeA
	TypeA* a_ptr1 = d_ptr;

	//b_ptr转换成其内部的TypeA子对象指针
	TypeA* a_ptr2 = b_ptr;

	//c_ptr转换成其内部的TypeA子对象指针
	TypeA* a_ptr3 = c_ptr;

	//先定位到c_ptr地址处,找到TypeC_Method1
	d_ptr->TypeC_Method1();

	//先定位到a_ptr地址处,找到TypeA_Method2
	c_ptr->TypeA_Method2();
    
    //先定位到a_ptr地址处,找到TypeA_Method1
	d_ptr->TypeA_Method1();
    
    //先定位到a_ptr地址处,找到TypeA_Method1
	c_ptr->TypeA_Method1();

	return 1;
}

1、d_ptr->TypeC_Method1()
发现TypeC_Method1是TypeC中定义的,所以找到TypeC子对象的地址,通过d_ptr+20,也是__vfptr的地址,再获取对应虚函数指针&TypeD::TypeC_Method1调用。因为是TypeD重写的函数,所以传入d_ptr作为this指针

2、c_ptr->TypeA_Method2()
发现TypeA_Method2是TypeA中定义的,所以找到TypeC部分的TypeA子对象地址,地址和c_ptr值一样,无需变更。通过c_ptr获取__vfptr值,再获取对应虚函数指针&TypeC::TypeA_Method2调用,因为是TypeC重写的函数,所以传入c_ptr作为this指针

3、d_ptr->TypeA_Method1()
发现TypeA_Method1是TypeA中定义,所以找到TypeB部分的TypeA子对象地址。再获取对应虚函数指针&TypeD::TypeA_Method1。因为是TypeD重写的函数,所以传入d_ptr作为this指针

4、c_ptr->TypeA_Method1()
发现是TypeA_Method1是TypeA中定义的,所以找到TypeC部分中的TypeA子对象地址。再获取对应虚函数指针&TypeD::TypeA_Method1。因为是TypeD重写的函数,所以传入c_ptr+20作为this指针

 

posted @ 2022-10-21 13:31  自由小菜园  阅读(23)  评论(0编辑  收藏  举报