[C++核心编程](九):类和对象——多态**

目录

多态的分类

多态的原理剖析

多态的优点

纯虚函数和抽象类

虚析构和纯虚析构


多态是C++面向对象三大特性之一

多态的分类

  • 静态多态

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

-函数地址绑定-编译阶段确定函数地址

  • 动态多态

-派生类虚函数实现运行时多态

-函数地址绑定-运行阶段确定函数地址

动态多态满足条件:

1.继承关系

2.子类要重写(函数返回值类型、函数名、参数列表完全相同)父类的虚函数

动态多态的使用:

父类的指针或者引用 指向 子类的对象

cpp 复制代码
#include <iostream>
#include <string>

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 test(void)
{
	Cat cat;
	dospeak(cat);

	Dog dog;
	dospeak(dog);
}

int main(void)
{
	test();
	return 0;
}

多态的原理剖析

父类内部结构vfptr-虚函数(表)指针 指向 vftable(表内记录虚函数的地址)

当子类重写父类的虚函数:子类中的虚函数表内部会替换成子类的虚函数地址

当父类的指针或者引用指向子类对象时,发生多态。

多态的优点

  • 代码组织结构清晰
  • 可读性强
  • 利于前期和后期的扩展和维护
  • (开闭原则)
cpp 复制代码
#include <iostream>
#include <string>

using namespace std;
//举例实现一个简易的计算器
class AbstractCalulator
{
public:
	//虚函数
	virtual int getResult()
	{
		return 0;
	}
	int n_number;
	int m_number;
};

class AddCalculator :public AbstractCalulator
{
public:
	int getResult()
	{
		return n_number + m_number;
	}
};

class SubCalculator :public AbstractCalulator
{
public:
	int getResult()
	{
		return n_number - m_number;
	}
};

class MulCalculator :public AbstractCalulator
{
public:
	int getResult()
	{
		return n_number * m_number;
	}
};

void test(void)
{
	AbstractCalulator* abc = new AddCalculator;
	abc->n_number = 10;
	abc->m_number = 10;

	cout << abc->n_number << "+" << abc->m_number << "=" << abc->getResult() << endl;
	delete abc;

	abc = new SubCalculator;
	abc->n_number = 10;
	abc->m_number = 10;

	cout << abc->n_number << "-" << abc->m_number << "=" << abc->getResult() << endl;
	delete abc;

	abc = new MulCalculator;
	abc->n_number = 10;
	abc->m_number = 10;

	cout << abc->n_number << "*" << abc->m_number << "=" << abc->getResult() << endl;
	delete abc;
}

int main(void)
{
	test();
	return 0;
}

纯虚函数和抽象类

在多态中,通常父类中虚函数的实现是毫无意义的,主要是调用子类重写的内容,因此可以将虚函数改为纯虚函数。

纯虚函数语法:virtual 返回值类型 函数名 (参数列表) = 0;

当类中有了纯虚函数,这个类被称为 抽象类

抽象类特点:

  • 无法实例化对象
  • 子类必须重写抽象类中的纯虚函数,否则也属于抽象类
cpp 复制代码
#include <iostream>
#include <string>

using namespace std;

class Base
{
public:
	virtual void func() = 0;

};

class Son:public Base
{
public:
	void func()
	{
		cout << "Son 's func()" << endl;
	}
};

void test(void)
{
	//Base base; 抽象类无法实例化对象
	//new Base;  抽象类无法实例化对象

	Base * base = new Son;
	base->func();
}

int main(void)
{
	test();
	return 0;
}

虚析构和纯虚析构

如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码导致内存泄漏 ,解决办法是将父类的析构函数改为虚析构 或者纯虚析构;

虚析构和纯虚析构的共性

  • 可以解决父类指针释放子类对象
  • 都需要具体的函数实现

虚析构和纯虚析构的区别

  • 如果是纯虚析构,该类属于抽象类,无法实例化对象

虚析构语法:virtual ~类名(){}

纯虚析构语法:virtual ~类名() = 0; 类名::~类名(){}

cpp 复制代码
#include <iostream>
#include <string>

using namespace std;

class AbstractAnimal
{
public:
	AbstractAnimal()
	{
		cout << "AbstractAnimal 构造函数调用" << endl;
	}
	//virtual ~AbstractAnimal()
	//{
	//	cout << "AbstractAnimal 析构函数调用" << endl;
	//}
	virtual ~AbstractAnimal() = 0;
	virtual void speak() = 0;
};

AbstractAnimal::~AbstractAnimal()
{
	cout << "AbstractAnimal 析构函数调用" << endl;
}

class Dog :public AbstractAnimal
{
public:
	Dog(string name)
	{
		cout << "Dog 构造函数调用" << endl;
		m_name = new string(name);
	}
	~Dog()
	{
		if (m_name != NULL)
		{
			cout << "Dog 析构函数调用" << endl;
			delete m_name;
			m_name = NULL;
		}
	}
	void speak()
	{
		cout << *m_name << "  Dog speaking" << endl;
	}
	string* m_name;
};

void test(void)
{
	AbstractAnimal* abs = new Dog("Tom");
	abs->speak();
	delete abs;
}

int main(void)
{
	test();
	return 0;
}

推荐文章:[C++核心编程](八):类和对象------继承**

相关推荐
cch89182 小时前
汇编与Java:底层与高层的编程对决
java·开发语言·汇编
荒川之神3 小时前
拉链表概念与基本设计
java·开发语言·数据库
chushiyunen3 小时前
python中的@Property和@Setter
java·开发语言·python
小樱花的樱花3 小时前
C++ new和delete用法详解
linux·开发语言·c++
froginwe113 小时前
C 运算符
开发语言
fengfuyao9854 小时前
低数据极限下模型预测控制的非线性动力学的稀疏识别 MATLAB实现
开发语言·matlab
摇滚侠4 小时前
搭建前端开发环境 安装 nodejs 设置淘宝镜像 最简化最标准版本 不使用 NVM NVM 高版本无法安装低版本 nodejs
java·开发语言·node.js
t198751284 小时前
MATLAB十字路口车辆通行情况模拟系统
开发语言·matlab
yyk的萌5 小时前
AI 应用开发工程师基础学习计划
开发语言·python·学习·ai·lua
Amumu121385 小时前
Js:正则表达式(一)
开发语言·javascript·正则表达式