[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++核心编程](八):类和对象------继承**

相关推荐
唐诺1 分钟前
几种广泛使用的 C++ 编译器
c++·编译器
高山我梦口香糖1 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
冷眼看人间恩怨1 小时前
【Qt笔记】QDockWidget控件详解
c++·笔记·qt·qdockwidget
信号处理学渣1 小时前
matlab画图,选择性显示legend标签
开发语言·matlab
红龙创客1 小时前
某狐畅游24校招-C++开发岗笔试(单选题)
开发语言·c++
Lenyiin1 小时前
第146场双周赛:统计符合条件长度为3的子数组数目、统计异或值为给定值的路径数目、判断网格图能否被切割成块、唯一中间众数子序列 Ⅰ
c++·算法·leetcode·周赛·lenyiin
jasmine s1 小时前
Pandas
开发语言·python
biomooc2 小时前
R 语言 | 绘图的文字格式(绘制上标、下标、斜体、文字标注等)
开发语言·r语言
骇客野人2 小时前
【JAVA】JAVA接口公共返回体ResponseData封装
java·开发语言
black^sugar2 小时前
纯前端实现更新检测
开发语言·前端·javascript