當(dāng)前位置:
首頁(yè) >
C++特性之多态,三个多态案例
發(fā)布時(shí)間:2024/3/24
39
豆豆
生活随笔
收集整理的這篇文章主要介紹了
C++特性之多态,三个多态案例
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
多態(tài)
多態(tài)的基本概念
多態(tài)是C++面向?qū)ο笕筇匦灾?/strong>
多態(tài)分為兩類
靜態(tài)多態(tài):函數(shù)重載 和 運(yùn)算符重載 屬于 靜態(tài)多態(tài),復(fù)用函數(shù)名
動(dòng)態(tài)多態(tài):派生類 和 虛函數(shù) 實(shí)現(xiàn)運(yùn)行時(shí)多態(tài)
靜態(tài)多態(tài)和動(dòng)態(tài)多態(tài)區(qū)別:
(1)靜態(tài)多態(tài)的函數(shù)地址早綁定? –? 編譯階段確定函數(shù)地址
(2)動(dòng)態(tài)多態(tài)的函數(shù)地址晚綁定? –? 運(yùn)行階段確定函數(shù)地址
下面通過(guò)案例進(jìn)行講解多態(tài)
#include<iostream>
using namespace std;//多態(tài)
class Animal{? ??
public:virtual?void speak(){?? ?//加上virtual后,函數(shù)變?yōu)樘摵瘮?shù)cout << "動(dòng)物在說(shuō)話" << endl;}
};
class Cat :: public Animal{
public:void speak(){cout << "小貓?jiān)谡f(shuō)話" << endl;}
}
18行:void doSpeak(Animal &animal){? ? //Animal &animal = cat??父類的引用在指向子類的對(duì)象//靜態(tài)多態(tài)animal.speak();? ? //這里調(diào)用的是父類的speak()函數(shù),也就是動(dòng)物在說(shuō)話,因?yàn)檫@里函數(shù)的地址是早綁定的,也就是一開(kāi)始就綁定了父類中的speak()函數(shù),在編譯階段就確定了函數(shù)地址//如果想執(zhí)行讓貓說(shuō)話,那么這個(gè)函數(shù)地址就不能提前綁定,需要在運(yùn)行階段進(jìn)行綁定,地址晚綁定,解決方法,在speak()函數(shù)前加virtual,將函數(shù)更改為虛函數(shù)//動(dòng)態(tài)多態(tài)animal.speak();? //這里就是貓?jiān)谡f(shuō)話}
void test01(){Cat cat;doSpeak(cat);? ??
}
int main(){test01();system("pause") ;return 0;
}
總結(jié):
動(dòng)態(tài)多態(tài)滿足條件
1、有繼承關(guān)系
2、子類要重寫(xiě)父類的虛函數(shù)(子類中重寫(xiě)函數(shù)時(shí)可以不用加virtual,但是父類中必須加)
動(dòng)態(tài)多態(tài)使用
父類的指針或者引用,執(zhí)行子類對(duì)象(也就是第18行的代碼)
多態(tài)的底層原理:
#include<iostream>
using namespace std;//多態(tài)
class Animal{????
public:void speak(){????//加上virtual后,函數(shù)變?yōu)樘摵瘮?shù)cout << "動(dòng)物在說(shuō)話" << endl;}
};
class Cat :: public Animal{
public:void speak(){cout << "小貓?jiān)谡f(shuō)話" << endl;}
}
void doSpeak(Animal &animal){????//Animal &animal = cat??父類的引用在指向子類的對(duì)象animal.speak();? ?animal.speak();??
}
void test01(){Cat cat;doSpeak(cat);????
}
void test02(){cout << "sizeof Animal = " << sizeof(Animal) << endl; //現(xiàn)在Animal類中只有一個(gè)非靜態(tài)的成員函數(shù),他不屬于類的對(duì)象,是分開(kāi)存儲(chǔ)的,那Animal相當(dāng)于是一個(gè)空類,那么他的大小就是sizeof(Animal) = 1;//如果加上virtual關(guān)鍵字,那么sizeof(Animal) = 4,這4個(gè)字節(jié)是一個(gè)指針,如圖1詳解
}
int main(){test01();test02();system("pause") ;return 0;
}
圖1
子類將父類拷貝一份之后speak函數(shù)的入口地址是Animal類中的speak函數(shù)地址,&Cat :: speak?這個(gè)代碼將speak函數(shù)的入口地址變?yōu)镃at對(duì)象的speak函數(shù)地址,然后會(huì)將原來(lái)子類中&Animal::speak函數(shù)的地址覆蓋掉,如下圖所示
這里就相當(dāng)于子類將父類的虛函數(shù)給替換掉了,但是父類中的虛函數(shù)并沒(méi)有發(fā)生改變
當(dāng)父類的指針或者引用指向子類對(duì)象的時(shí)候,發(fā)生多態(tài)
Animal *animal = cat ;
animal.speak();
由于指向的是一個(gè)cat對(duì)象,那么他會(huì)去cat的虛函數(shù)表中去找speak函數(shù),這是在運(yùn)行階段
?
多態(tài)案例一-計(jì)算器類
案例描述:
分別利用普通寫(xiě)法和多態(tài)技術(shù),設(shè)計(jì)實(shí)現(xiàn)兩個(gè)操作數(shù)進(jìn)行運(yùn)算的計(jì)算器類
多態(tài)的優(yōu)點(diǎn):
(1)代碼組織結(jié)構(gòu)清晰
(2)可讀性強(qiáng)
(3)利于前期和后期的擴(kuò)展以及維護(hù)
include<iostream>
using namespace std;//分別利用普通寫(xiě)法和多態(tài)技術(shù)實(shí)現(xiàn)計(jì)算器
//普通寫(xiě)法
class Calculator{
public:int?getResu1t(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;}//如果想擴(kuò)展新的功能,需要修改源碼int m_Num1 ;//操作數(shù)1int m_Num2;//操作數(shù)2
};void test01(){
//創(chuàng)建計(jì)算器對(duì)象Caiculator c;c.m_Num1 = 10;c.m_Num2 = 10;cout << c.m_Num1 << " + " << c.m_Num2〈<<" = " << c.getResult("+") << end1;//20cout << c.m_Num1 << " - " << c.m_Num2〈<<" = " << c.getResult("-") << end1;//0cout << c.m_Num1 << " * " << c.m_Num2〈<<" = " << c.getResult("*") << end1;//100
}//利用多態(tài)實(shí)現(xiàn)計(jì)算器
//實(shí)現(xiàn)計(jì)算器抽象類
class AbstractCalculator
public:virtual?int getResult(){return 0;}int m_Num1;int m_Num2;
};
//加法計(jì)算器類
class AddCalculator : public AbstractCalculator{
public:virtual int getResult(){return m_Num1 + m_Num2;}
}
//減法計(jì)算器類
class SubCalculator : public AbstractCalculator{
public:virtual int getResult(){return m_Num1 - m_Num2;}
}
void test02(){//多態(tài)使用條件//父類指針或者引用指向子類對(duì)象AbstractCalculator * abc = new AddCalculator;abc->m_Num1 = 10;abc->m_Num2 = 10;cout << abc->m_Num1 <<"+"<< abc->m_Num2<< " = " << abc->getResult() << endl;//用完記得銷毀delete abc;abc = new SubCalculator;abc->m_Num1 = 10;abc->m_Num2 = 10;cout << abc->m_Num1 <<"-"<< abc->m_Num2<< " = " << abc->getResult() << endl;delete abc;
}
int main(){test01();test02();system("pause");return 0;
}
多態(tài)帶來(lái)的好處:
1、組織結(jié)構(gòu)清晰
2、可讀性強(qiáng)
3、對(duì)于前期和后期擴(kuò)展以及維護(hù)性高
案例三:
案例描述:
?? ??? ?電腦主要組成部件為CPU(用于計(jì)算),顯卡(用于顯示),內(nèi)存條(用于存儲(chǔ))
?? ??? ?將每個(gè)零件封裝出抽象基類,并且提供不同的廠商生產(chǎn)不同的零件,例如Intel廠商和Lenovo廠商創(chuàng)建電腦類提供讓電腦工作的函數(shù),并且調(diào)用每個(gè)零件工作的接口
?? ??? ?測(cè)試時(shí)組裝三臺(tái)不同的電腦進(jìn)行工作
#include <iostream> #include <string> using namespace std;class CPU{ public:virtual void run_CPU() = 0; }; class Screem{ public:virtual void run_screem() = 0; }; class RAM{ public:virtual void run_ram() = 0; }; class Computer{ public:Computer(CPU *cpu,Screem *screem,RAM *ram){m_CPU = cpu;m_screem = screem;m_RAM = ram;}~Computer(){if(m_CPU == NULL){delete m_CPU;m_CPU = NULL;}if(m_screem == NULL){delete m_screem;m_screem = NULL;}if(m_RAM == NULL){delete m_RAM;m_RAM = NULL;}}void dowork(){m_CPU->run_CPU();m_screem->run_screem();m_RAM->run_ram();} private:CPU *m_CPU;Screem *m_screem;RAM *m_RAM; }; ostream &operator <<(ostream &cout,string &string){cout << string.c_str()<<endl;return cout; } class Inter_CPU:public CPU{ public:virtual void run_CPU(){cout << " Inter_CPU is running!"<<endl;} }; class Inter_Screem:public Screem{ public:virtual void run_screem(){cout <<" Inter_SCREEM is running!"<<endl;} }; class Inter_RAM:public RAM{ public:virtual void run_ram(){cout << " Inter_RAM is running!"<<endl;} }; void test01(){Inter_CPU inter_cpu;Inter_Screem inter_screem;Inter_RAM inter_ram;CPU *F_CPU = &inter_cpu;Screem *F_SCREEM = &inter_screem;RAM *F_RAM = &inter_ram;Computer(F_CPU,F_SCREEM,F_RAM).dowork(); } int main(){test01();system("pause");return 0; }總結(jié)
以上是生活随笔為你收集整理的C++特性之多态,三个多态案例的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 自动超频_电脑超频有什么用?一键超频原来
- 下一篇: 一维激波C++编程