c++ 多态 运行时多态和编译时多态_C++核心编程 第十一节 多态
前言:多態(tài)是C++面向?qū)ο笕筇匦灾弧?/p>
多態(tài),指的是一個類實例的相同方法在不同情形有不同表現(xiàn)形式。具有不同內(nèi)部結(jié)構(gòu)的對象可以共享外部接口。C++多態(tài)就是用一個更通用的基類指針指向不同的子類實例,為了能調(diào)用正確的方法,我們需要用到虛函數(shù)和虛繼承。
#include using namespace std;class Animal{public: // Speak函數(shù)就是虛函數(shù) // 函數(shù)前面加上 virtual 關(guān)鍵字變成虛函數(shù),那么編譯器在編譯的時候就不能確定函數(shù)的調(diào)用了 virtual void speak(){ cout << "動物在說話" << endl; }};class Cat : public Animal{public: void speak(){ cout << "小貓在說話" << endl; }};class Dog : public Animal{public: void speak(){ cout << "小狗在說話" << endl; }};// 希望傳入什么對象,那么就調(diào)用什么對象的函數(shù)// 如果函數(shù)地址在編譯階段就能確定,那么靜態(tài)聯(lián)編// 如果函數(shù)地址在運行階段才能確定,就是動態(tài)聯(lián)編void DoSpeak(Animal & animal){ animal.speak(); }// 多態(tài)滿足條件:// 1、有繼承關(guān)系// 2、子類重寫父類中的虛函數(shù)// 多態(tài)使用:// 父類指針或引用指向子類對象void test(){ Cat cat; DoSpeak(cat); Dog dog; DoSpeak(dog);}int main(){ test(); return 0;}多態(tài)案例——計算器類
案例描述:分別利用普通寫法和多態(tài)技術(shù),設(shè)計實現(xiàn)兩個操作數(shù)進行運算的計算器類。
#include#includeusing namespace std;class Calculator{public: int getResult(string oper){ if(oper == "+"){ return m_Num1 + m_Num2; } else if(oper == "-"){ return m_Num1 - m_Num2; } else if (oper == "*"){ return m_Num1 * m_Num2; } // 如果要提供新的運算,需要修改源碼 } int m_Num1; int m_Num2;};void test(){ // 普通實現(xiàn)測試 Calculator c; c.m_Num1 = 10; c.m_Num2 = 20; cout << c.m_Num1 << " + " << c.m_Num2 << " = " << c.m_Num1 + c.m_Num2 << endl; cout << c.m_Num1 << " - " << c.m_Num2 << " = " << c.m_Num1 - c.m_Num2 << endl; cout << c.m_Num1 << " * " << c.m_Num2 << " = " << c.m_Num1 * c.m_Num2 << endl;}// 多態(tài)實現(xiàn)// 抽象計算器類// 多態(tài)優(yōu)點:代碼組織結(jié)構(gòu)清晰,可讀性強,利于前期和后期的擴展以及維護class AbstractCalculator{public: virtual int getResult(){ return 0;} int m_Num1; int m_Num2;};// 加法計算器class AddCalculator : public AbstractCalculator{public: int getResult(){ return m_Num1 + m_Num2; }};// 減法計算器class SubCalculator : public AbstractCalculator{public: int getResult(){ return m_Num1 - m_Num2; }};// 乘法計算器class MulCalculator : public AbstractCalculator{public: int getResult(){ return m_Num1 * m_Num2; }};void test2(){ // 創(chuàng)建加法計算器 AbstractCalculator *abc = new AddCalculator; abc->m_Num1 = 10; abc->m_Num2 = 20; cout << abc->m_Num1 << " + " << abc->m_Num2 << " = " << abc->getResult() << endl; delete abc; // 用完了銷毀 // 創(chuàng)建減法計算器 abc = new SubCalculator; abc->m_Num1 = 10; abc->m_Num2 = 20; cout << abc->m_Num1 << " - " << abc->m_Num2 << " = " << abc->getResult() << endl; delete abc; // 創(chuàng)建乘法計算器 abc = new MulCalculator; abc->m_Num1 = 10; abc->m_Num2 = 20; cout << abc->m_Num1 << " * " << abc->m_Num2 << " = " << abc->getResult() << endl; delete abc;}int main(){ test(); test2(); return 0;}總結(jié):C++開發(fā)提倡利用多態(tài)設(shè)計程序架構(gòu),因為多態(tài)優(yōu)點很多。
純虛函數(shù)和抽象類
在多態(tài)中,通常父類中虛函數(shù)的實現(xiàn)沒有意義,主要都是調(diào)用子類重寫的內(nèi)容。因此可以將虛函數(shù)改為純虛函數(shù)。
#includeusing namespace std;class Base{public: // 純虛函數(shù) // 類中只要有一個純虛函數(shù)就稱為抽象類 // 抽象類無法實例化對象 // 子類必須重寫父類中的純虛函數(shù),否則也屬于抽象類 virtual void func() = 0;};class Son : public Base{public: virtual void func(){ cout << "func調(diào)用" << endl; }};void test(){ Base * base = NULL;// base = new Base; // 抽象類無法實例化對象 base = new Son; base->func(); delete base;}int main(){ test(); return 0;}多態(tài)案例二—制作飲品
案例描述:制作飲品的大致流程為:煮水 - 沖泡 - 倒入杯中 - 加入輔料
利用多態(tài)技術(shù)實現(xiàn)本案例,提供抽象制作飲品基類,提供子類制作茶水和咖啡。
#includeusing namespace std;class AbstractDringking{public: // 燒水 virtual void Boil() = 0; // 沖泡 virtual void Brew() = 0; // 倒入杯中 virtual void PourInCup() = 0; // 加入輔料 virtual void PutSomething() = 0; // 規(guī)定流程 void MakeDrink(){ Boil(); Brew(); PourInCup(); PutSomething(); }};// 制作茶水class Tea : public AbstractDringking{public: void Boil(){ cout << "煮農(nóng)夫山泉" << endl; } void Brew(){ cout << "沖泡茶葉" << endl; } void PourInCup(){ cout << "將茶水倒入杯中" << endl; } void PutSomething(){ cout << "加入枸杞" << endl; }};// 制作咖啡class Coffee : public AbstractDringking{public: void Boil(){ cout << "煮純凈水" << endl; } void Brew(){ cout << "沖泡咖啡" << endl; } void PourInCup(){ cout << "將咖啡倒入杯中" << endl; } void PutSomething(){ cout << "加入牛奶" << endl; }};// 業(yè)務(wù)函數(shù)void Dowork(AbstractDringking* drink){ drink->MakeDrink(); delete drink;}void test(){ Dowork(new Tea); cout << "----------------------" << endl; Dowork(new Coffee);}int main(){ test(); return 0;}虛析構(gòu)和純虛析構(gòu)
多態(tài)使用時,如果子類中有屬性開辟到堆區(qū),那么父類指針在釋放時無法調(diào)用到子類的析構(gòu)代碼。
解決方式:將父類中的析構(gòu)函數(shù)改為虛析構(gòu)或者純虛析構(gòu)。
#includeusing namespace std;class Animal{public: Animal(){ cout << "Animal構(gòu)造函數(shù)" << endl; } virtual void Speak() = 0; // 析構(gòu)函數(shù)加上virtual關(guān)鍵字,變成虛析構(gòu)函數(shù)// virtual ~Animal(){// cout << "Animal虛析構(gòu)函數(shù)" << endl;// } virtual ~Animal() = 0;};Animal::~Animal() { cout << "Animal 純虛析構(gòu)函數(shù)" << endl; }// 和包含普通純虛函數(shù)的類一樣,包含類普通純虛析構(gòu)函數(shù)的類也是一個抽象類。不能夠被實例化。class Cat : public Animal{public: Cat(string name){ cout << "Cat構(gòu)造函數(shù)" << endl; m_Name = new string(name); } virtual void Speak(){ cout << *m_Name << "小貓在說話" << endl; } ~Cat(){ cout << "Cat析構(gòu)函數(shù)" << endl; if(this->m_Name != NULL) delete m_Name; m_Name = NULL; } string *m_Name;};void test(){ Animal *animal = new Cat("Tom"); animal->Speak(); // 通過父類指針去釋放,會導(dǎo)致子類對象可能清理不干凈,造成內(nèi)存泄露 // 怎么解決?給基類增加一個虛析構(gòu)函數(shù) // 虛析構(gòu)函數(shù)就是用來解決父類指針釋放子類對象 delete animal;}int main(){ test(); return 0;}總結(jié):
1、虛析構(gòu)或純虛析構(gòu)就是用來解決通過父類指針釋放子類對象
2、如果子類中沒有堆區(qū)數(shù)據(jù),可以不寫為虛析構(gòu)或純虛析構(gòu)
3、擁有純虛析構(gòu)函數(shù)的類也屬于抽象類
多態(tài)案例三 - 電腦組裝
案例描述:電腦主要組成部件為CPU(用于計算),顯卡(用于顯示),內(nèi)存條(用于存儲)
將每個零件封裝出抽象基類,并且提供不同的廠商生產(chǎn)不同的零件,例如Intel廠商和Lenovo廠商。
創(chuàng)建電腦類提供讓電腦工作的函數(shù),并且調(diào)用每個零件工作的接口。
#includeusing namespace std;// 抽象CPU類class CPU{public: // 抽象的計算函數(shù) virtual void calculate() = 0;};// 抽象顯卡類class VideoCard{public: virtual void display() = 0;};// 抽象內(nèi)存條類class Memory{public: virtual void storage() = 0;};class Computer{public: Computer(CPU * cpu, VideoCard * vc, Memory * men){ m_cpu = cpu; m_vc = vc; m_men = men; } // 提供工作的函數(shù) void work(){ // 讓零件工作起來,調(diào)用接口 m_cpu->calculate(); m_vc->display(); m_men->storage(); } // 提供析構(gòu)函數(shù),釋放三個電腦零件 ~Computer(){ if(m_cpu != NULL){ delete m_cpu; m_cpu = NULL; } if(m_vc != NULL){ delete m_vc; m_vc = NULL; } if(m_men != NULL){ delete m_men; m_men = NULL; } }private: CPU * m_cpu; VideoCard * m_vc; Memory * m_men;};// 具體廠商// Intel廠商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的內(nèi)存條開始存儲了" << endl; }};// Lenovo廠商class LenovoCPU : public CPU{public: virtual void calculate(){ cout << "Lenovo的CPU開始計算" << endl; }};class LenovoVideoCard : public VideoCard{public: virtual void display(){ cout << "Lenovo的顯卡開始顯示了" << endl; }};class LenovoMemory : public Memory{public: virtual void storage(){ cout << "Lenovo的內(nèi)存條開始存儲了" << endl; }};void test(){ // 第一條電腦零件 CPU * intelCpu = new IntelCPU; VideoCard * intelCard = new IntelVideoCard; Memory * intelMem = new IntelMemory; cout << "Intel零件組裝電腦開始工作:" << endl; // 創(chuàng)建第一臺電腦 Computer * computer1 = new Computer(intelCpu, intelCard, intelMem); computer1->work(); delete computer1; cout << "------------------------" << endl; cout << "Lenovo零件組裝電腦開始工作:" << endl; // 組裝第二臺電腦 Computer * computer2 = new Computer(new LenovoCPU, new LenovoVideoCard, new LenovoMemory); computer2->work(); delete computer2; cout << "------------------------" << endl; cout << "混裝零件電腦開始工作:" << endl; Computer * computer3 = new Computer(new LenovoCPU, new IntelVideoCard, new LenovoMemory); computer3->work(); delete computer3;}int main(){ test(); return 0;}????????????????????? ? - END -
總結(jié)
以上是生活随笔為你收集整理的c++ 多态 运行时多态和编译时多态_C++核心编程 第十一节 多态的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql 主键倒序查询速度慢_一亿条数
- 下一篇: vb6 方法‘ ’作用于对象 失败_JS