动态多态的实现和虚析构和纯虚析构(c++)

首先需要明确多态性的用途,是为了接口的最大程度复用,以及其定义:

多态性的定义,可以简单地概括为“一个接口,多种方法”,程序在运行时才决定调用的函数,它是面向对象编程领域的核心概念。多态(polymorphism),字面意思多种形状。多态分为静态多态和动态多态。
静态多态是通过重载和模板技术实现,在编译的时候确定。
动态多态通过虚函数和继承关系来实现,执行动态绑定,在运行的时候确定。

定义明确,接下来看看最常见的动态多态的实现思路:对于一组相关的数据类型,抽象出它们之间共同的功能集合,在基类中将共同的功能声明为多个公共虚函数接口,子类通过重写这些虚函数,实现各自对应的功能。在调用时,通过基类的指针来操作这些子类对象,所需执行的虚函数会自动绑定到对应的子类对象上。

上述可以看出,动态多态的实现关键在于虚函数,基类通过virtual关键字声明和实现虚函数,此时基类会拥有一张虚函数表,虚函数表会记录其对应的函数指针。当子类继承基类时,子类也会获得一张虚函数表,不同之处在于,子类如果重写了某个虚函数,其在虚函数表上的函数指针会被替换为子类的虚函数指针。

1.实现代码

#include<iostream>
using namespace std;

// 动物类
class Animal {
public:
	//虚函数
	virtual  void speak() {
		cout << "动物在说话" << endl;
	}
};
// 猫类
class Cat :public Animal
{
public:
	void speak()
	{
		cout << "小猫在说话" << endl;
	}
};
//狗类
class Dog :public Animal {
public:
	void speak()
	{
		cout << "小狗在说话" << endl;
	}
};
//执行说话的函数
//地址早绑定  在编译阶段提前确定函数地址
//如果想执行让猫说话,那么这个函数地址就不能提前绑定,需要在运行阶段进行绑定,地址晚绑定
//利用动态多态
void doSpeak(Animal& animal) {
	animal.speak();
}
void test01()
{
	Animal animal;
	doSpeak(animal);
	Cat cat;
	doSpeak(cat);
	Dog dog;
	doSpeak(dog);
}


//分别利用普通写法和多态技术实现计算器

//普通写法
class Calculator {
public:
	int retResult(string oper)
	{
		if (oper == "+")
		{
			return m_num1 + m_num2;
		}
		else if (oper == "-")
		{
			return m_num1 - m_num2;
		}
		else if (oper == "*")
		{
			return m_num1 * m_num2;
		}
		else
		{
			return m_num1 / m_num2;
		}
		//如果想扩展新的功能,需求修改源码
		//在真是开发中提倡开闭原则
		//开闭原则:对扩展进行开发2,对修改代码进行关闭
	}
	int m_num1;
	int m_num2;
};
void test02()
{
	//创建计算器操作数
	Calculator c;
	c.m_num1 = 10;
	c.m_num2 = 10;
	cout << c.retResult("+");

}


//利用多态实现计算器
class AbstractCalculator
{
public:
	virtual int getResult()
	{
		return 0;
	}
	int m_num1;
	int m_num2;
};

//加法计算器
class AddCalulator:public AbstractCalculator
{
public:
	int getResult()
	{
		return m_num1 + m_num2;
	}
};
//加法计算器
class SubCalulator :public AbstractCalculator
{
public:
	int getResult()
	{
		return m_num1 - m_num2;
	}
};
//乘法计算器
//加法计算器
class MultCalulator :public AbstractCalculator
{
public:
	int getResult()
	{
		return m_num1 * m_num2;
	}
};
void test03()
{
	//多态的使用条件
	//父类指针或者引用指向子类对象
	
	//加法运算
	AbstractCalculator* abc = new AddCalulator;
	abc->m_num1 = 10;
	abc->m_num2 = 10;

	cout << abc->m_num1 << "+" << abc->m_num2 << " = " << abc->getResult() << endl;
	delete abc;


}
int main()
{
	test01();
	test03();
}

2.虚析构和纯虚析构

虚析构函数和纯虚析构函数区别在哪里?作为两点介绍:

1、虚析构函数:

主要作用是为了来解决基类指针指向派生类对象,并用基类指针释放派生类对象。也就是说父类的虚析构函数,会调用派生类的析构函数。有虚析构函数的类是抽象类,不能实例化对象,不需要在类外实现;

2、纯虚析构函数:

有纯虚析构函数的类它是抽象类,不能实例化对象,而且要在类外实现;

#include<iostream>
#include<string>
using namespace std;

// 动物类
class Animal {
public:
	//纯虚函数
	Animal()
	{
		cout << "animal 构造函数调用" << endl;
	}
	virtual  void speak()=0;//这种写法仅仅适合构建纯虚函数
	/*virtual  void speak() {
		cout << "动物在说话" << endl;
	}*/


	//利用虚析构可以解决  父类指针释放子类对象不干净的问题
	virtual ~Animal()
	{
		cout << "animal 虚析构函数调用" << endl;
	}

	/*~Animal()
	{
		cout << "animal 析构函数调用" << endl;
	}*/

		//纯虚析构声明也需要实现
		//有了纯虚析构之后,这个类也属于抽象类,无法实例化对象
	 // virtual ~Animal()=0;    //这样写会报错,因为这样只是一个声明
};

//纯虚析构
//Animal:: ~Animal()
//{
//	cout << "animal 纯虚析构函数调用" << endl;
//}

class Cat :public Animal
{
public:
	Cat(string name)
	{
		cout << "cat 构造函数调用"<<endl;
		m_name = new string(name);

	}
	virtual void speak()
	{
		cout << *m_name<< "小猫在说话" << endl;
	}
	~Cat()
	{	
		cout << "cat析构函数调用"<<endl;
		delete m_name;
		m_name = NULL;
	}
	string* m_name;
};

void test01()
{
	Animal* animal = new Cat("tom");
	animal->speak();
	//父类指针在析构函数,不会调用子类中的析构函数,导致子类如果有堆区属性,出现内存泄漏。
	delete animal;
}
int main()
{
	test01();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值