C++入门学习:多态的概念及其原理

多态的目标:一种调用语句有多种不同的表现形态

根据实际的对象类型来判断重写函数的调用
如果父类指针指向的是父类对象则调用父类中定义的函数

如果父类指针指向的是子类对象则调用子类中定义的重写函数

实现的手段:通过虚函数来实现(下面会具体介绍)

虚函数:在函数声明的没钱加virtual 关键字,该函数就变为虚函数。(内联函数、静态函数、构造函数不能是虚函数)

多态实现的条件:

1、要有继承

2、要有虚函数重写

3、用基类指针指向派生类对象

具体事例和注释:

#include <iostream>

using namespace std;

//基类
class Animal
{
public:
	void eat()
	{
		cout << "动物吃饭" << endl;
	}
	//虚函数
	virtual void sleep()
	{
		cout << "动物睡觉" <<endl;
	}
};

class Cat:public Animal
{
public:
	//函数重定义
	void eat()
	{
		cout << "猫吃鱼" << endl;
	}

	//虚函数的重定义 =====> 函数重写
	void sleep()
	{
		cout << "猫睡觉" << endl;
	}
};

class Fish:public Animal
{
public:
	//函数重定义
	void eat()
	{
		cout << "鱼吃虾" << endl;
	}

	//虚函数的重定义 =====> 函数重写
	void sleep()
	{
		cout << "鱼睁眼睡觉" << endl;
	}
};


//基类指针
//期望做的事:同样的调用语句
//1、当基类指针指向基类对象的时候,调用基类自己的成员函数
//2、当基类指针指向派生类对象的时候,调用派生类的同名成员函数

//======》多态:一种调用语句有多种不同的表现形态
//======》实现:通过 虚函数 来实现 ------》在函数声明前加 virtual 关键字,该函数就变为虚函数

//预处理、编译、汇编、连接
void func(Animal *pa)
{
	//指针的行为受限于指针的类型
	//pa是Animal类型,所以只能执行Animal 内部的方法

	//编译器执行流程
	//1、判断 pa 的类型----->Animal类型
	//2、判断 eat()函数类型 ----->是个普通函数
	//3、结果:因为是普通函数,所以按照指针类型调用,
	//由1知识Animal类型,所以直接调用Animal::eat()
	//上述流程是在编译期间就已经知道如何处理如何运行----->这种就叫做静态联编 (早期绑定)
	pa->eat();


	//1、判断 pa 的类型----->Animal类型
	//2、判断 sleep()函数类型 ----->是个 虚函数
	//3、结果:因为是虚函数,所以编译器不知道调用谁的函数
	//---->会通过某种机制,找到 最终需要调用的函数(和传过来的对象有关)
	//上述这种在编译期间无法知道具体如何处理、
	//需要在 运行的时候 根据传入的对象才能确定具体调用------>动态联编 迟绑定
	pa->sleep();
}


int main()
{
	Animal a;
	Cat    c;
	Fish   f;
	func(&a);
	cout << "-------------" << endl;

	func(&c);
	cout << "-------------" << endl;

	func(&f);
	cout << "-------------" << endl;
	return 0;
}

多态的原理

#include <iostream>

using namespace std;

class Animal
{
public:
	//类中有虚函数则,类的内存模型中,会有一个虚函数指针(vfptr)
	//用来指向当前类的需函数表,该指针排列在对象的开始部分
	//虚函数指针(vfptr) 要优先于 虚基类指针(vbptr)
	//基类中有vfptr指针则 派生类中也会有,即基类中的虚函数,派生类中同名的函数也是虚函数()
	virtual void eat()
	{
		cout << "动物吃饭" << endl;
	}

	void sleep()
	{
		cout << "动物睡觉" << endl;
	}
private:
	int a;
};

class Cat:public Animal
{
public:
	virtual void eat()
	{
		cout << "猫吃饭" << endl;
	}

	void sleep()
	{
		cout << "猫睡觉" << endl;
	}

private:
	int b;
};


void func(Animal *pa)//用基类指针接受派生类对象地址
{
	/*多态原理:
	如何确定传过来的对象类型?======》如何找到传过来的对象的相应函数?
	多态的实现依靠虚函数====》虚函数做了什么?
	1、根据传过来的对象找到对应的类,通过基类指针 找到该类的虚函数指针
	2、通过虚函数指针找到 虚函数表
	3、在虚函数表中找到 需要执行的函数
	*/
	pa->eat(); //pa->vfptr->eat();
	pa->sleep();
}


int main()
{
	cout << sizeof(Animal) << endl;
	cout << sizeof(Cat) << endl;

	Animal a;
	Cat c, c1, c2;//&c == &c1 == &c2,有虚函数的类会有一张虚函数表
				//该类对象模型中最上面会有一个虚函数指针,该指针指向自身类的虚函数表
				//虚函数表具有唯一性,一个类只有一张虚函数表

	func(&a);
	func(&c);

	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值