在面向对象的程序设计中,使用多态能够增强程序的可扩充性,即程序需要修改或增加功能时,只需改动或增加较少的代码。此外,使用多态也能起到精简代码的作用。
多态优点
- 代码组织结构清晰
- 可读性强
- 利于前期和后期的扩展以及维护
初识多态
1 #include <iostream> 2 using namespace std; 3 /*多态分为两类 4 静态多态:函数重载和运算符重载属于静态多态,复用函数名 5 动态多态:派生类和虚函数实现运行时多态 6 7 静态多态和动态多态区别: 8 静态多态的函数地址早绑定 - 编译阶段确定函数地址 9 动态多态的函数地址晚绑定 - 运行阶段确定函数地址 10 */ 11 //动物类 12 class Animal{ 13 public: 14 //虚函数 15 virtual void speak(){ 16 cout<<"动物在说话"<<endl; 17 } 18 }; 19 //猫类 20 class Cat:public Animal{ 21 public: 22 void speak(){ 23 cout<<"小猫在叫唤"<<endl; 24 } 25 }; 26 27 //狗类 28 class Dog:public Animal{ 29 public: 30 void speak(){ 31 cout<<"小狗在说话"<<endl; 32 } 33 }; 34 35 //执行说话的函数 36 //地址早绑定 在编译阶段确定函数地址 37 //如果想执行让猫说话,那么这个函数地址就不能提前绑定 38 //需要在运行阶段进行绑定,地址晚绑定 39 void doSpeak(Animal &animal){ 40 animal.speak(); 41 } 42 43 /* 44 动态多态满足条件 45 1、有继承关系 46 2、子类重写父类的虚函数 47 //重写 函数返回值类型 函数名 参数列表 完全相同 48 49 50 动态多态使用 51 父类的指针或者引用 指向子类对象 52 */ 53 void test01(){ 54 Cat cat; 55 doSpeak(cat); 56 Dog dog; 57 doSpeak(dog); 58 } 59 int main() 60 { 61 test01(); 62 return 0; 63 }初始多态
对比普通写法与多态写法
1 #include <iostream> 2 using namespace std; 3 //案例描述: 4 /*分别利用普通写法和多态技术, 5 设计实现两个操作数进行运算 6 的计算器类 7 */ 8 /*多态优点 9 代码组织结构清晰 10 可读性强 11 利于前期和后期的扩展以及维护*/ 12 13 class Calculator{ 14 public: 15 Calculator(int num1,int num2){ 16 m_Num1=num1; 17 m_Num2=num2; 18 } 19 int getResult(string oper) 20 { 21 if(oper == "+"){ 22 return m_Num1+m_Num2; 23 } 24 else if(oper=="-"){ 25 return m_Num1 - m_Num2; 26 } 27 else if(oper == "*"){ 28 return m_Num1 * m_Num2; 29 } 30 } 31 32 int m_Num1; 33 int m_Num2; 34 }; 35 36 //利用多态实现 37 //多态好处: 38 //1、组织结构清晰 39 //2、可读性强 40 //3、对于前期和后期拓展 41 42 class AbstractCalculator{ 43 public: 44 virtual int getResult(){ 45 return 0; 46 } 47 48 int m_Num1; 49 int m_Num2; 50 }; 51 52 //加法计算器类 53 class AddCalculator :public AbstractCalculator{ 54 public: 55 int getResult(){ 56 return m_Num1+m_Num2; 57 } 58 }; 59 //减法计算器类 60 class SubCalculator :public AbstractCalculator{ 61 public: 62 int getResult(){ 63 return m_Num1-m_Num2; 64 } 65 }; 66 //乘法计算器类 67 class ProCalculator :public AbstractCalculator{ 68 public: 69 int getResult(){ 70 return m_Num1*m_Num2; 71 } 72 }; 73 void test01(){ 74 Calculator calculator(1,2); 75 76 cout<<"calculator.getResult(1,2);oper=+; res="<<calculator.getResult("+")<<endl; 77 } 78 79 void test02(){ 80 //多态使用条件 81 //父类指针或者引用指向子类对象 82 83 //加法运算 84 AbstractCalculator *abc = new AddCalculator; 85 abc->m_Num1=10; 86 abc->m_Num2=10; 87 cout<<abc->m_Num1<<"+"<<abc->m_Num2<<"="<<abc->getResult()<<endl; 88 delete abc; 89 //减法运算 90 abc = new SubCalculator; 91 abc->m_Num1=100; 92 abc->m_Num2=90; 93 cout<<abc->m_Num1<<"-"<<abc->m_Num2<<"="<<abc->getResult()<<endl; 94 delete abc; 95 //乘法运算 96 abc = new ProCalculator; 97 abc->m_Num1=7; 98 abc->m_Num2=8; 99 cout<<abc->m_Num1<<"*"<<abc->m_Num2<<"="<<abc->getResult()<<endl; 100 delete abc; 101 } 102 103 int main() 104 { 105 // test01(); 106 test02(); 107 return 0; 108 }多态案例1_计算器类
纯虚函数与抽象类,一个父类指针访问调用不同子类的成员
1 #include <iostream> 2 using namespace std; 3 /* 4 在多态中,通常父类中虚函数的实现是毫无意义的, 5 主要都是调用子类重写的内容 6 7 因此可以将虚函数改为纯虚函数 8 9 纯虚函数语法: 10 virtual 返回值类型 函数名 (参数列表)=0; 11 12 当类中有了纯虚函数,这个类也称为抽象类 13 */ 14 /*抽象类特点 15 无法实例化对象 16 子类必须重写抽象类中的纯虚函数,否则也属于抽象类 17 18 */ 19 20 21 class Base{ 22 public: 23 //这就是纯虚函数 24 virtual void func()=0; 25 }; 26 27 class Son:public Base{ 28 public: 29 void func(){ 30 cout<<"Son类的func()"<<endl; 31 } 32 }; 33 34 void test01(){ 35 Son s; 36 s.func(); 37 38 //多态 一个父类指针访问调用不同子类的成员 39 Base * base=new Son; 40 base->func(); 41 } 42 int main() 43 { 44 test01(); 45 return 0; 46 }纯虚函数与抽象类
体验纯虚函数与抽象类
1 #include <iostream> 2 using namespace std; 3 /* 4 制作饮品的大致流程为: 5 煮水-冲泡-倒入杯中-加入辅料 6 */ 7 8 class AbstractDrinking{ 9 public: 10 virtual void Boil()=0; 11 virtual void Brew()=0; 12 virtual void PourInCup()=0; 13 virtual void PutSomething()=0; 14 15 void makeDrink(){ 16 Boil(); 17 Brew(); 18 PourInCup(); 19 PutSomething(); 20 } 21 }; 22 23 class Coffee:public AbstractDrinking{ 24 public: 25 void Boil(){ 26 cout<<"煮水"<<endl; 27 } 28 void Brew(){ 29 cout<<"冲泡"<<endl; 30 } 31 void PourInCup(){ 32 cout<<"倒入杯中"<<endl; 33 } 34 void PutSomething(){ 35 cout<<"加入牛奶和糖"<<endl; 36 } 37 }; 38 39 class Tea:public AbstractDrinking{ 40 public: 41 void Boil(){ 42 cout<<"煮水"<<endl; 43 } 44 void Brew(){ 45 cout<<"冲泡茶叶"<<endl; 46 } 47 void PourInCup(){ 48 cout<<"倒入杯中"<<endl; 49 } 50 void PutSomething(){ 51 cout<<"加入柠檬"<<endl; 52 } 53 }; 54 void test01(){ 55 AbstractDrinking *abs=new Coffee; 56 abs->makeDrink(); 57 cout<<"========================"<<endl; 58 abs=new Tea; 59 abs->makeDrink(); 60 delete abs; 61 } 62 63 int main() 64 { 65 test01(); 66 return 0; 67 }多态案例2_制作饮品
利用虚析构可以解决 父类指针释放子类对象时不干净的问题
1 #include <iostream> 2 using namespace std; 3 4 5 /*多态使用时,如果子类中有属性开辟到堆区 6 那么父类指针在释放时无法调用到子类的析构代码 7 8 解决方式:将父类中的析构函数改为虚析构或者纯虚析构 9 10 */ 11 /*虚析构和春虚析构共性: 12 可以解决父类指针释放子类对象 13 都需要有具体的函数实现 14 */ 15 /*虚析构和纯虚析构区别 16 如果是纯虚析构,该类属于抽象类, 17 无法实例化对象 18 */ 19 /* 20 虚析构语法 21 virtual -类名(){} 22 纯虚析构语法: 23 virtual ~类名()=0; 24 */ 25 26 class Animal{ 27 public: 28 Animal(){ 29 cout<<"Animal的构造函数"<<endl; 30 } 31 ////利用虚析构可以解决 父类指针释放子类对象时不干净的问题 32 // virtual ~Animal(){ 33 // cout<<"Animal的析构函数"<<endl; 34 // } 35 //纯虚析构 36 virtual ~Animal()=0; 37 //纯虚函数 38 virtual void speak()=0; 39 }; 40 41 Animal::~Animal(){ 42 cout<<"Animal的纯虚析构函数"<<endl; 43 } 44 class Cat:public Animal{ 45 public: 46 Cat(string name){ 47 cout<<"这是Cat的构造函数"<<endl; 48 m_Name = new string(name); 49 } 50 void speak(){ 51 cout<<*m_Name<<"小猫在说话"<<endl; 52 } 53 ~Cat(){ 54 cout<<"这是Cat的析构函数"<<endl; 55 if(m_Name != NULL){ 56 delete m_Name; 57 m_Name=NULL; 58 } 59 } 60 string *m_Name; 61 }; 62 63 void test01(){ 64 65 Animal * animal=new Cat("Tom"); 66 animal->speak(); 67 //父类指针在析构时候 不会调用子类中析构函数, 68 //导致子类如果有堆区属性 ,出现内存泄露 69 delete animal; 70 } 71 72 int main() 73 { 74 test01(); 75 76 77 return 0; 78 }虚析构和纯虚析构
进一步体验,感受指针的使用。还看到有句弹幕“谁创建,谁清除”
1 #include <iostream> 2 using namespace std; 3 4 /*案例描述 5 电脑主要组成部件为CPU(用于计算),显卡(用于显示), 6 内存条(用于存储)将每个零件封装出抽象基类,并且提供 7 不同厂商生产不同的零件,例如Intel厂商和lenovo 8 厂商创建电脑类提供让电脑工作的函数,并且调用每个零件 9 工作的接口,测试时组装三台不同的电脑进行工作 10 */ 11 12 class CPU{ 13 public : 14 virtual void calculate()=0; 15 }; 16 class VideoCard{ 17 public: 18 virtual void display()=0; 19 }; 20 class Memory{ 21 public: 22 virtual void storage()=0; 23 }; 24 class Computer{ 25 public: 26 Computer(CPU * cpu,VideoCard *vc,Memory *mem){ 27 m_cpu=cpu; 28 m_vc=vc; 29 m_mem=mem; 30 } 31 //提供工作的函数 32 void work(){ 33 m_cpu->calculate(); 34 m_vc->display(); 35 m_mem->storage(); 36 } 37 //提供析构函数 释放3个电脑零件 38 ~Computer(){ 39 if(m_cpu!=NULL){ 40 delete m_cpu; 41 m_cpu=NULL; 42 cout<<"m_cpu释放"<<endl; 43 } 44 if(m_vc!=NULL){ 45 delete m_vc; 46 m_vc=NULL; 47 cout<<"m_vc释放"<<endl; 48 } 49 if(m_mem!=NULL){ 50 delete m_mem; 51 m_mem=NULL; 52 cout<<"m_mem释放"<<endl; 53 } 54 } 55 private: 56 CPU *m_cpu; 57 VideoCard *m_vc; 58 Memory * m_mem; 59 }; 60 61 class IntelCPU:public CPU{ 62 public: 63 virtual void calculate(){ 64 cout<<"IntelCPU开始计算了!"<<endl; 65 } 66 }; 67 class IntelVideoCard:public VideoCard{ 68 public: 69 virtual void display(){ 70 cout<<"IntelVideoCard开始显示啦!"<<endl; 71 } 72 }; 73 class IntelMemory:public Memory{ 74 public: 75 virtual void storage(){ 76 cout<<"IntelMemory开始存储了!"<<endl; 77 } 78 }; 79 80 void test01(){ 81 CPU * intelCpu = new IntelCPU; 82 VideoCard * intelCard = new IntelVideoCard; 83 Memory * intelMem = new IntelMemory; 84 Computer *IntelComputer=new Computer(intelCpu,intelCard,intelMem); 85 IntelComputer->work(); 86 delete IntelComputer; 87 } 88 89 class LenovoCPU:public CPU{ 90 public: 91 virtual void calculate(){ 92 cout<<"LenovoCPU开始计算了!"<<endl; 93 } 94 }; 95 class LenovoVideoCard:public VideoCard{ 96 public: 97 virtual void display(){ 98 cout<<"LenovoVideoCard开始显示啦!"<<endl; 99 } 100 }; 101 class LenovoMemory:public Memory{ 102 public: 103 virtual void storage(){ 104 cout<<"LenovoMemory开始存储了!"<<endl; 105 } 106 }; 107 108 void test02(){ 109 CPU * lenovoCpu = new LenovoCPU; 110 VideoCard * lenovoCard = new LenovoVideoCard; 111 Memory * lenovoMem = new LenovoMemory; 112 Computer *LenovoComputer = new Computer(lenovoCpu,lenovoCard,lenovoMem); 113 LenovoComputer->work(); 114 delete LenovoComputer; 115 } 116 int main() 117 { 118 test01(); 119 cout<<"\r\n"; 120 test02(); 121 122 cout<<"\r\n"; 123 Computer *computer3 = new Computer(new LenovoCPU,new IntelVideoCard,new IntelMemory); 124 computer3->work(); 125 delete computer3; 126 127 return 0; 128 }多态案例3_电脑组装
标签:函数,int,void,多态,public,class From: https://www.cnblogs.com/hwq123/p/17686249.html