多态的基本语法
多态分为二类:静态多态和动态多态
》》》静态多态:函数重载和运算符重载属于静态多态
》》》动态多态:派生类和虚函数实现运行时多态
静态多态和动态多态区别:静态多态的函数地址早绑定(编译阶段确认函数地址)动态多态的函数地址晚绑定(运行阶段确认函数地址)
程序举例
#include <iostream>
using namespace std;
class Animal {
public:
void speak() {
cout << "动物在说话!" << endl;
}
};
class Cat :public Animal{
public:
void speak() {
cout << "小猫在说话!" << endl;
}
};
void doSpeak(Animal &a) {
a.speak();
}
int main() {
Cat c1;
c1.speak();
doSpeak(c1);
system("pause");
return 0;
}
此处我们使用虚函数实现晚绑定
#include <iostream>
using namespace std;
class Animal {
public:
virtual void speak() {
cout << "动物在说话!" << endl;
}
};
class Cat :public Animal{
public:
void speak() {
cout << "小猫在说话!" << endl;
}
};
void doSpeak(Animal &a) {
a.speak();
}
int main() {
Cat c1;
c1.speak();
doSpeak(c1);
system("pause");
return 0;
}
动态多态要求满足的条件:有继承关系;子类重写父类的虚函数
多态案例1 - 计算器类
原始实现
#include <iostream>
using namespace std;
#include <string>
class Calculate {
public:
Calculate(int num1, int num2) {
Num1_ = num1;
Num2_ = num2;
}
int getResult(string oper){
if (oper == "+") {
return Num1_ + Num2_;
}
else if (oper == "-") {
return Num1_ - Num2_;
}
else if (oper == "*") {
return Num1_ * Num2_;
}
else if (oper == "/") {
return Num1_ / Num2_;
}
}
public:
int Num1_;
int Num2_;
};
int main() {
Calculate c1(3, 4);
cout << c1.getResult("+") << endl;
cout << c1.getResult("-") << endl;
cout << c1.getResult("*") << endl;
cout << c1.getResult("/") << endl;
system("pause");
return 0;
}
多态实现
#include <iostream>
using namespace std;
class Calculate {
public:
virtual int getResult() {
return 0;
}
public:
int Num1_;
int Num2_;
};
class Add :public Calculate{
public:
virtual int getResult() {
return Num1_ + Num2_;
}
};
class Sub :public Calculate {
public:
virtual int getResult() {
return Num1_ - Num2_;
}
};
class Mul :public Calculate {
public:
virtual int getResult() {
return Num1_ * Num2_;
}
};
class Div :public Calculate {
public:
virtual int getResult() {
return Num1_ / Num2_;
}
};
int main() {
Calculate *cal1 = new Add;
cal1->Num1_ = 10;
cal1->Num2_ = 2;
cout << cal1->getResult() << endl;
Calculate *cal2 = new Sub;
cal2->Num1_ = 10;
cal2->Num2_ = 2;
cout << cal2->getResult() << endl;
Calculate *cal3 = new Mul;
cal3->Num1_ = 10;
cal3->Num2_ = 2;
cout << cal3->getResult() << endl;
Calculate *cal4 = new Div;
cal4->Num1_ = 10;
cal4->Num2_ = 2;
cout << cal4->getResult() << endl;
system("pause");
return 0;
}
优点:组织结构清晰;可读性强;对与前期和后期扩展以及维护性高
纯虚函数和抽象类
在多态中通常父类中虚函数的实现都是毫无意义的,主要调用子类中重写的内容
》》》因此可以将虚函数改为纯虚函数
纯虚函数语法:virtual 返回值类型 函数名 (参数列表) = 0;
》》》当类中存在纯虚函数,这个类也称为抽象类
抽象类特点
》》》无法实例化对象 》》》子类必须重写抽象类中的纯虚函数否则也属于抽象类
程序举例
#include <iostream>
using namespace std;
class Base {
public:
virtual void func() = 0;
};
class Son :public Base{
};
int main() {
system("pause");
return 0;
}
多态案例2 - 学科学习过程
#include <iostream>
using namespace std;
class AbstractStudying {
public:
virtual void AjustMind() = 0;
virtual void StudyMethod() = 0;
virtual void ConcernDegree() = 0;
virtual void Repay() = 0;
void doWork() {
AjustMind();
StudyMethod();
ConcernDegree();
Repay();
}
};
class Math :public AbstractStudying{
public:
virtual void AjustMind() {
cout << "数学学习心态:10 分" << endl;
}
virtual void StudyMethod() {
cout << "数学学习方法:10 分" << endl;
}
virtual void ConcernDegree() {
cout << "数学认真程度:10 分" << endl;
}
virtual void Repay() {
cout << "数学学习回报:10 分" << endl;
}
};
class English :public AbstractStudying{
public:
virtual void AjustMind() {
cout << "英语学习心态:10 分" << endl;
}
virtual void StudyMethod() {
cout << "英语学习心态:10 分" << endl;
}
virtual void ConcernDegree() {
cout << "英语学习心态:10 分" << endl;
}
virtual void Repay() {
cout << "英语学习心态:10 分" << endl;
}
};
int main() {
AbstractStudying *abs1 = new Math;
abs1->doWork();
cout << "-------------------" << endl;
AbstractStudying *abs2 = new English;
abs2->doWork();
system("pause");
return 0;
}
虚析构和纯虚析构
多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用子类的析构函数,也就不能释放子类中开辟到堆区的属性
》》》解决方式:将父类中的析构函数改为虚析构或纯虚析构
虚析构和纯虚析构共性
》》》可以解决父类指针释放子类对象
》》》都需要有具体的函数实现
虚析构和纯虚析构区别
》》》如果是纯虚析构,该类属于抽象类,无法实例化对象
程序举例
#include <iostream>
using namespace std;
#include <string>
class Animal {
public:
Animal() {
cout << "Animal 构造函数实现" << endl;
}
virtual ~Animal() = 0;
virtual void Speak() = 0;
};
Animal::~Animal() {
cout << "Animal 纯虚析构函数实现" << endl;
}
class Cat :public Animal{
public:
~Cat(){
if (Name_ != NULL) {
delete Name_;
Name_ = NULL;
}
cout << "Cat 纯虚析构函数实现" << endl;
}
Cat(string name) {
Name_ = new string(name);
cout << "Cat 构造函数实现" << endl;
}
virtual void Speak() {
cout << "小猫" << *Name_ << "在说话!" << endl;
}
public:
string *Name_;
};
void func() {
Animal *aml = new Cat("苏苏");
aml->Speak();
delete aml;
}
int main() {
func();
system("pause");
return 0;
}
多态案例3 - 电脑组装
#include <iostream>
using namespace std;
class CPU {
public:
virtual void Calculate() = 0;
};
class VideoCard {
public:
virtual void Display() = 0;
};
class Memory {
public:
virtual void Storage() = 0;
};
class IntelCPU :public CPU{
public:
virtual void Calculate() {
cout << "Intel 的 CPU 开始工作了!" << endl;
}
};
class IntelVideoCard :public VideoCard {
public:
virtual void Display() {
cout << "Intel 的 显卡 开始工作了!" << endl;
}
};
class IntelMemory :public Memory {
public:
virtual void Storage() {
cout << "Intel 的 内存条 开始工作了!" << endl;
}
};
class HPCPU :public CPU {
public:
virtual void Calculate() {
cout << "HP 的 CPU 开始工作了!" << endl;
}
};
class HPVideoCard :public VideoCard {
public:
virtual void Display() {
cout << "HP 的 显卡 开始工作了!" << endl;
}
};
class HPMemory :public Memory {
public:
virtual void Storage() {
cout << "HP 的 内存条 开始工作了!" << endl;
}
};
class Computer {
public:
Computer(CPU *cpu, VideoCard * videocard, Memory *memory) {
Cpu_ = cpu;
Videocard_ = videocard;
Memory_ = memory;
}
~Computer() {
if (Cpu_ != NULL) {
delete Cpu_;
Cpu_ = NULL;
}
if (Videocard_ != NULL) {
delete Videocard_;
Videocard_ = NULL;
}
if (Memory_ != NULL) {
delete Memory_;
Memory_ = NULL;
}
cout << "电脑零件:CPU、显卡和内存条占用的堆区内存已被释放!" << endl;
}
void Work() {
Cpu_->Calculate();
Videocard_->Display();
Memory_->Storage();
}
private:
CPU *Cpu_;
VideoCard * Videocard_;
Memory *Memory_;
};
void func() {
CPU *cpu = new HPCPU;
VideoCard *videocard = new HPVideoCard;
Memory *memory = new HPMemory;
Computer *computer = new Computer(cpu, videocard, memory);
computer->Work();
delete computer;
cout << "-----------------------------------------------" << endl;
Computer *computer2 = new Computer(new IntelCPU, new IntelVideoCard, new IntelMemory);
computer2->Work();
delete computer2;
}
int main() {
func();
system("pause");
return 0;
}
|