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;
}
运行结果: