动态多态的注意事项

大家好:

        衷心希望各位点赞。

        您的问题请留在评论区,我会及时回答。

多态的基本概念

多态是C++面向对象三大特性之一(多态、继承、封装)

多态分为两类:

静态多态:函数重载和运算符重载属于静态多态,复用函数名。

动态多态:通过派生类和虚函数实现运行时多态。

静态多态和动态多态的区别:

静态多态的函数地址早绑定——编译阶段确定函数地址。

动态多态的函数地址晚绑定——运行阶段确定函数地址。

下面通过案例讲解多态:

#include 
#include 

using namespace std;

class Animal
{
public:
	void speak()
	{
		cout << "动物在说话" << endl;
	}
};

class Cat : public Animal
{
public:

	// 重写父类中的函数
	void speak()
	{
		cout << "小猫在说话" << endl;
	}
};

// 执行说话的函数
void doSpeak(Animal& animal)
{
	animal.speak();
}


int main(void)
{
	Cat cat;
	doSpeak(cat); // 父类引用接收子类对象
	

	system("pause");
	return 0;
}

运行截图:

        全局函数doSpeak()在编译阶段就确定了它的地址——函数地址早绑定,即使形参传入基类Animal的任何子类,子类已经重写了基类的speak()函数。doSpeak() 函数只会调用基类Animal的speak()函数。但是,我们想执行这行代码doSpeak(cat)的时候,输出“小猫在说话”。即:在运行阶段,根据函数doSpeak()传入的实参类型,再去决定具体执行哪个类的成员函数。

        如果想要实现“小猫在说话”,那么函数地址就不能早绑定,必须在程序运行阶段进行绑定,即:动态多态的函数地址晚绑定——运行阶段确定函数地址。

        在父类的成员函数前加上关键字 virtual ,使其变成虚函数,并且在子类中重写父类的虚函数即可。

#include 
#include 

using namespace std;

class Animal
{
public:
	virtual void speak() // 虚函数
	{
		cout << "动物在说话" << endl;
	}
};

class Cat : public Animal
{
public:

	// 重写父类中的虚函数
	virtual void speak()
	{
		cout << "小猫在说话" << endl;
	}
};

class Dog : public Animal
{
	// 重写父类中的虚函数
	virtual void speak()
	{
		cout << "小狗在说话" << endl;
	}
};

// 执行说话的函数
void doSpeak(Animal& animal)
{
	// 在运行阶段,才能确定函数speak()的地址,即:根据实参类型,才能确定执行哪个speak()函数
	animal.speak(); 
}


int main(void)
{
	Cat cat;
	doSpeak(cat); // 调用类Cat的speak()

	cout << "----------" << endl;

	Dog dog;
	doSpeak(dog); // 调用类Dog的speak()
	

	system("pause");
	return 0;
}

运行截图:

动态多态的注意事项_第1张图片

         实现了:在程序运行时,根据实参类型,决定执行哪一个子类重写的函数。程序执行到doSpeak(cat)这行代码时,编译器检测到实参类型是Cat类,就会调用Cat类的speak()函数。程序执行到doSpeak(dog)这行代码时,编译器检测到实参类型是Dog类,就会调用Dog类的speak()函数。

        注意:子类重写父类的虚函数,可以省略 virtual 关键字。

总结

动态满足条件:

1、有继承关系

2、子类重写父类的虚函数

函数重写:函数首部完全相同,函数体不同,函数重写发生在子类中。

动态多态的使用

父类的指针或引用接收子类对象,调用子类重写的父类函数,就会发生动态多态。

你可能感兴趣的:(动态多态,静态多态,虚函数,子类重写父类虚函数实现动态多态)