18.继承多态笔试题实战分析

Posted 为了财务自由!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了18.继承多态笔试题实战分析相关的知识,希望对你有一定的参考价值。

class Animal

public:
	Animal(string name) :_name(name) 
	// 纯虚函数
	virtual void bark() = 0;
protected:
	string _name;
;
// 以下是动物实体类
class Cat : public Animal

public:
	Cat(string name) :Animal(name) 
	void bark()  cout << _name << " bark: miao miao!" << endl; 
;
class Dog : public Animal

public:
	Dog(string name) :Animal(name) 
	void bark()  cout << _name << " bark: wang wang!" << endl; 
;


50-51:
p11[0]访问的是Cat前四个字节,p22[0]访问的是Dog前四个字节。
后续三行操作意思是交换前四个字节,那么Cat前四个字节放的就是Dog虚函数表地址(虚函数指针)Dog前四个字节放的就是Cat虚函数表地址(虚函数指针)
那么执行出来就是加菲猫汪汪叫,二哈喵喵叫!

class Base

public:
	virtual void show(int i = 10)
	
		cout << "call Base::show i:" << i << endl;
	
;
class Derive : public Base

public:
	void show(int i = 20)
	
		cout << "call Derive::show i:" << i << endl;
	
;
int main()

	Base *p = new Derive(); // 虚析构函数
	/*
	push 0Ah => 函数调用,参数压栈是在编译时期就确定好的
	mov eax, dword ptr[p]
	mov ecx, dword ptr[eax]
	call ecx
	*/
	p->show(); // 动态绑定 p-> Derive vfptr -> Derive vftable
	delete p;

	return 0;


调用的是派生类的方法,但是参数却是10?
编译阶段,p->show()编译器只能看到Base里的show方法,那么就将参数入栈:
push 0Ah => 函数调用,参数压栈是在编译时期就确定好的
接下来动态绑定(三句汇编):
mov eax, dword ptr[p]
mov ecx, dword ptr[eax]
call ecx
也就是说在编译时,10这个参数就入栈了!

class Base

private://public
	virtual void show()
	
		cout << "call Base::show" << endl;
	
;
class Derive : public Base

public:
	void show()
	
		cout << "call Derive::show" << endl;
	
;
int main()

	Base* p = new Derive();
	/*
	成员方法能不能调用,就是说方法的访问权限是不是public的,是在编译阶段就需要确定
	好的

	编译阶段 Base::show
	call Base::show   call ecx
	*/
	//“Base::show”: 无法访问 private 成员(在“Base”类中声明)
	p->show(); // 最终能调用到Derive::show,是在运行时期才确定的
	delete p;
	return 0;

class Base

public:
	Base()
	
		//进函数前 先开辟函数栈帧,然后把虚函数表放进去!:
		/*
		push ebp
		mov ebp, esp
		sub esp, 4Ch
		rep stos esp<->ebp 0xCCCCCCCC(windows VS GCC/G++)
		vfptr <- &Base::vftable
		*/
		cout << "call Base()" << endl;
		clear();
	
	//前四个字节为虚函数表地址,那么这个函数就把他变成0地址了...
	//那么动态绑定的时候,就访问不到虚函数表了,0地址犯法!
	void clear()  memset(this, 0, sizeof(*this)); 
	virtual void show()
	
		cout << "call Base::show()" << endl;
	
;
class Derive : public Base

public:
	Derive()
	
		/*
		push ebp
		mov ebp, esp
		sub esp, 4Ch
		rep stos esp<->ebp 0xCCCCCCCC(windows VS GCC/G++)
		vfptr <- &Derive::vftable
		*/
		cout << "call Derive()" << endl;
	
	void show()
	
		cout << "call Derive::show()" << endl;
	
;
int main()

	//Base *pb1 = new Base();
	/*
	mov eax, dword ptr[pb1]
	mov ecx, dword ptr[eax] eax:0x00000000 不是Base::vftable
	call ecx
	*/
	//pb1->show(); // 动态绑定
	//delete pb1;

	Base *pb2 = new Derive();
	// 动态绑定 call Derive::show()
	/*
	vfptr里面存储的是vftable的地址
	vfptr <- vftable
	*/
	pb2->show(); 
	//先调用Base构造函数,对虚函数表地址清零,然后调用Derive构造函数,
	//进构造函数前,开辟函数栈帧,然后指向虚函数表,所以可以正常运行!
	//而Base *pb1 = new Base();pb1->show();报错!
	delete pb2;

	return 0;

以上是关于18.继承多态笔试题实战分析的主要内容,如果未能解决你的问题,请参考以下文章

2018年网易Java笔试题

C++笔试试题讲解(~~~可能是全站唯独一份有解析的~~~)

动态内存函数+经典笔试题@动态内存管理---malloc +free + calloc + realloc

动态内存管理详解(动态内存函数介绍 + 常见动态内存错误 + 经典笔试题)

c++复习笔记——多态详细解析,多态的原理,多态的笔试题

C语言——动态内存管理经典笔试题+柔性数组