2021-05-16 C++多态计算器例子,仅供自己笔记

本文通过一个C++多态计算器的例子,展示了如何利用继承和多态实现不同运算的计算器类。讨论了多态带来的代码结构清晰、可读性和扩展性优势。同时,解释了在父类指针指向子类对象时,如果没有虚析构函数,可能导致子类析构函数未被调用,从而引起内存泄漏的问题。文章提供了虚析构函数和纯虚析构函数的解决方案,并通过实际代码运行结果对比,说明了两者的区别和应用场景。
摘要由CSDN通过智能技术生成

C++多态计算器例子,仅供自己笔记

案例描述:

分别利用多态技术,设计实现两个操作数进行运算的计算器类

多态的优点:

  • 代码组织结构清晰
  • 可读性强
  • 利于前期和后期的扩展以及维护
#include <iostream>
using namespace std;
class BaseCalculater {
public:
	virtual int getResult()=0;
	int a;
	int b;
};

class AddCalculater:public BaseCalculater {
public:
	int getResult() {
		return a + b;
	}
};
class SubCalculater :public BaseCalculater {
public:
	int getResult() {
		return a - b;
	}
};
class MulCalculater :public BaseCalculater {
public:
	int getResult() {
		return a * b;
	}
};

int main() {
	//加法计算器
	BaseCalculater* calculater = new AddCalculater;
	calculater->a = 10;
	calculater->b = 10;
	cout << calculater->a << "+" << calculater->b << "=" << calculater->getResult() << endl;
	delete calculater;
	//减法计算器
	calculater = new SubCalculater;
	calculater->a = 10;
	calculater->b = 10;
	cout << calculater->a << "-" << calculater->b << "=" << calculater->getResult() << endl;
	delete calculater;
	//乘法计算器
	calculater = new MulCalculater;
	calculater->a = 10;
	calculater->b = 10;
	cout << calculater->a << "*" << calculater->b << "=" << calculater->getResult() << endl;
	delete calculater;
	return 0;
}

子类父类构造析构的调用情况
为子类父类写出构造函数和析构函数(写出输出语句),测试构造函数和析构函数的调用顺序

class BaseCalculater {
public:
	virtual int getResult() = 0;
	BaseCalculater() {
		cout << "父类的构造函数" << endl;
	}
	~BaseCalculater() {
		cout << "父类的析构函数" << endl;
	}
	int a;
	int b;
};

class AddCalculater:public BaseCalculater {
public:
	int getResult() {
		return a + b;
	}
	AddCalculater() {
		cout << "子类的构造函数" << endl;
	}
	~AddCalculater() {
		cout << "子类的析构函数" << endl;
	}
};
BaseCalculater* calculater = new AddCalculater();
	calculater->a = 10;
	calculater->b = 10;
	cout << calculater->a << "+" << calculater->b << "=" << calculater->getResult() << endl;
	delete calculater;

运行结果:
在这里插入图片描述
如果父类不存在虚函数,构造函数的调用顺序应该是父->子,析构是子->父,但是很明显这里并没有调用到子类的析构。在本例中,子类没有新开辟堆空间内存,没有额外开辟占用堆空间的属性,所以子类没有调用析构也不影响啥,但是一旦子类存在新开辟堆空间的情况,未析构,就会造成内存泄漏。

综上,父类指针析构的时候不会调用子类的析构函数,如果子类有堆区属性会内存泄漏。

解决方案:
虚析构和纯虚析构
多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码

解决方式:将父类中的析构函数改为虚析构或者纯虚析构

虚析构和纯虚析构共性:

  • 可以解决父类指针释放子类对象

  • 都需要有具体的函数实现

虚析构和纯虚析构区别:

如果是纯虚析构,该类属于抽象类,无法实例化对象
虚析构语法:virtual ~类名(){}

纯虚析构语法:virtual ~类名() = 0;
纯虚析构在类的内部声明,并且需要在类的外面进行实现类名::~类名(){}

1.利用虚析构
将上述代码父类的虚构函数改成:

	virtual ~BaseCalculater() {
		cout << "父类的析构函数" << endl;
	}

运行结果:
在这里插入图片描述
2.利用纯虚析构

class BaseCalculater {
public:
	virtual int getResult() = 0;
	BaseCalculater() {
		cout << "父类的构造函数" << endl;
	}
	virtual ~BaseCalculater() = 0;
	int a;
	int b;
};
BaseCalculater::~BaseCalculater() {
	cout << "父类的纯虚析构函数" << endl;
}

运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值