一個(gè)接口有多種形態(tài),傳入的對(duì)象不一樣,同一個(gè)接口執(zhí)行的操作不同
成都創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),青秀企業(yè)網(wǎng)站建設(shè),青秀品牌網(wǎng)站建設(shè),網(wǎng)站定制,青秀網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷,網(wǎng)絡(luò)優(yōu)化,青秀網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。
多態(tài)分為兩類
靜態(tài)多態(tài)胡動(dòng)態(tài)多態(tài)的區(qū)別
早綁定
#include<iostream>
using namespace std;
class Animal{ //父類
public:
void speak(){
cout << "動(dòng)物在說(shuō)話" << endl;
}
};
class Cat:public Animal{ //子類
public:
void speak(){
cout << "小貓?jiān)谡f(shuō)話" << endl;
}
};
//地址早綁定
void doSpeak(Animal &animal){ //等價(jià)于 Animal &animal = cat;
animal.speak();
}
void test01(){
Cat cat;
doSpeak(cat);//本意輸出貓?jiān)谡f(shuō)話
}
int main(){
test01();
return 0;
}
晚綁定(只要在父類的函數(shù)前面加一個(gè)virtual)
virtual void speak(){
cout << "動(dòng)物在說(shuō)話" << endl;
}
動(dòng)態(tài)多態(tài)的滿足條件
動(dòng)態(tài)多態(tài)的使用
在使用virtual后父類結(jié)構(gòu)改變,多列一個(gè)指針(虛函數(shù)表指針),指向一個(gè)虛函數(shù)表,在虛函數(shù)表中寫(xiě)著虛函數(shù)函數(shù)入口地址
子類重寫(xiě)虛函數(shù)時(shí),會(huì)把原來(lái)的虛函數(shù)替換成子類新寫(xiě)的虛函數(shù)(如果不重寫(xiě),則虛函數(shù)表中的數(shù)據(jù)和父類是一樣的)
所以用父類的引用去指向子類對(duì)象時(shí),當(dāng)調(diào)用公共的接口(虛函數(shù))時(shí),會(huì)從子類中去尋找確實(shí)的函數(shù)地址,
多態(tài)的優(yōu)點(diǎn):
#include<iostream>
using namespace std;
class Calculator{//計(jì)算器類
public:
int getResult(string oper){
if(oper == "+") return m_a + m_b;
if(oper == "-") return m_a - m_b;
if(oper == "*") return m_a * m_b;
}
int m_a;
int m_b;
};
void test01(){
Calculator C;
C.m_a = 10;
C.m_b = 10;
cout << C.m_a << "+" << C.m_b << "=" << C.getResult("+") << endl;
cout << C.m_a << "-" << C.m_b << "=" << C.getResult("-") << endl;
cout << C.m_a << "*" << C.m_b << "=" << C.getResult("*") << endl;
}
int main(){
test01();
return 0;
}
但是我們發(fā)現(xiàn),這個(gè)計(jì)算器是沒(méi)有除法的,要想添加除法,必須去源碼中修改,但是
在真實(shí)開(kāi)發(fā)中,提倡:開(kāi)閉原則(對(duì)拓張進(jìn)行開(kāi)放,對(duì)修改進(jìn)行關(guān)閉)
所以我們來(lái)用多態(tài)的方式來(lái)寫(xiě)一下吧
//乘法、除法的計(jì)算器就不寫(xiě)了
#include<iostream>
using namespace std;
class Calculator{ //虛基類
public:
virtual int getResult(){ //只要個(gè)名字,沒(méi)有任何功能
return 0;
}
int m_a;
int m_b;
};
class SonAdd:public Calculator{ //加法類
public:
int getResult(){
return m_a + m_b;
}
};
class SonSub:public Calculator{ //減法類
public:
int getResult(){
return m_a - m_b;
}
};
class SonMul:public Calculator{ //乘法類
public:
int getResult(){
return m_a * m_b;
}
};
class SonDiv:public Calculator{ //除法類
public:
int getResult(){
return m_a / m_b;
}
};
void test01(){//這次我們使用指針的方法來(lái)指向子類對(duì)象
Calculator * C = new SonAdd;//加法計(jì)算器
C->m_a = 10;
C->m_b = 10;
cout << C->m_a << "+" << C->m_b << "=" << C->getResult() << endl;
delete C;//new在堆區(qū),要記得釋放哦
C = new SonSub; //減法計(jì)算器
C->m_a = 20;
C->m_b = 20;
cout << C->m_a << "-" << C->m_b << "=" << C->getResult() << endl;
delete C;
}
int main(){
test01();
return 0;
}
在多態(tài)中,通常父類中虛函數(shù)的實(shí)現(xiàn)是沒(méi)有意義的,主要都是調(diào)用子類中重寫(xiě)的內(nèi)容
因此可以將虛函數(shù)改為純虛函數(shù)
當(dāng)類中出現(xiàn)了純虛函數(shù),這個(gè)類就叫做抽象類
virtual 返回值類型 函數(shù)名 (參數(shù)列表) = 0;
#include<iostream>
using namespace std;
class Base{//抽象類
public:
virtual void func() = 0;
};
class Son:public Base{ //子類
public:
void func(){ //重寫(xiě)函數(shù)是
cout << "子類重寫(xiě)成功" <<endl;
}
};
void use(Base &base){//引用來(lái)實(shí)現(xiàn)
base.func();
}
void test01(){
Son son;
use(son);
cout << "=========================" << endl;
Base * base = new Son;//指針來(lái)實(shí)現(xiàn)
base->func();
}
int main(){
test01();
return 0;
}
在原本的代碼上稍稍優(yōu)化了一下
#include<iostream>
using namespace std;
class Base{ //抽象類
public:
virtual void Boll() = 0;
virtual void Brew() = 0;
virtual void Pour() = 0;
virtual void AddSome() = 0;
void make(){//調(diào)用制作飲品的函數(shù)
Boll();
Brew();
Pour();
AddSome();
}
};
class Tea:public Base{//茶類
public:
void Boll(){
cout << "1.煮茶水" << endl;
}
void Brew(){
cout << "2.沖泡茶葉" << endl;
}
void Pour(){
cout << "3.倒入茶杯中" << endl;
}
void AddSome(){
cout << "4.加入輔料" << endl;
}
};
class Coffee:public Base{ //咖啡類
public:
void Boll(){
cout << "1.煮水" << endl;
}
void Brew(){
cout << "2.沖泡咖啡" << endl;
}
void Pour(){
cout << "3.倒入咖啡杯中" << endl;
}
void AddSome(){
cout << "4.加入輔料(牛奶/放糖)" << endl;
}
};
void domake(Base *base){ //多態(tài)的實(shí)現(xiàn)
base->make();
delete base;
}
void test01(){ //制作茶
domake(new Tea);
}
void test02(){ //制作咖啡
//domake(new Coffee);
Base * base = new Coffee;
base->make();
delete base;
}
void select(){ //選擇要制作的飲品
int i = 0;
const int j = 3; //最大的制作次數(shù)
while(1){
cout << "請(qǐng)選擇所需要的飲品(您現(xiàn)在最多可以選" << j-i << "次)" << endl;
string drink;
cin >> drink;
if(drink == "茶"){
test01();
}else if(drink == "咖啡"){
test02();
}else{
cout << "對(duì)不起,您所選的飲品目前沒(méi)有..." << endl;
}
i += 1;
if(i == j) break;//達(dá)到3次后結(jié)束
}
return;
}
int main(){
select();
return 0;
}
多態(tài)使用時(shí),父類的指針或引用子類時(shí),如果子類中有屬性開(kāi)辟到堆區(qū),那么父類指針在釋放時(shí)無(wú)法調(diào)用子類的析構(gòu)函數(shù)
所以,我們將父類中的析構(gòu)函數(shù)改為(純)虛析構(gòu)
析構(gòu)和純虛析構(gòu)的共性
析構(gòu)和純虛析構(gòu)的區(qū)別
虛析構(gòu):
virtual ~類名(){}
純虛析構(gòu):
virtual ~類名() = 0;//類內(nèi)
類名::~類名(){}//類外
#include<iostream>
using namespace std;
class Animal{ //父類
public:
Animal(){
cout << "Animal構(gòu)造調(diào)用" << endl;
}
~Animal(){
cout << "Animal析構(gòu)調(diào)用" << endl;
}
virtual void speak() = 0;
};
class Cat:public Animal{ //子類
public:
Cat(string name){
cout << "Cat構(gòu)造調(diào)用" << endl;
m_Name = new string(name);
}
~Cat(){
if(m_Name != NULL){
cout << "Cat析構(gòu)調(diào)用" << endl;
delete m_Name;
m_Name = NULL;
}
}
void speak(){
cout << *m_Name << "小貓會(huì)說(shuō)話" << endl;
}
string *m_Name;//要?jiǎng)?chuàng)建在堆區(qū)
};
void test01(){
Animal * animal = new Cat("Tom");
animal->speak();
delete animal;
}
int main(){
test01();
return 0;
}
沒(méi)有調(diào)用Cat的析構(gòu)函數(shù),數(shù)據(jù)沒(méi)有清楚干凈,可能會(huì)造成內(nèi)存泄露
原因:父類指針指向子類,delete父類時(shí),不會(huì)調(diào)用子類的析構(gòu)代碼
解決:使用虛析構(gòu)函數(shù)
virtual ~Animal(){
cout << "Animal析構(gòu)調(diào)用" << endl;
}
結(jié)果
300
內(nèi)部要有函數(shù)的實(shí)現(xiàn),不能只是下面這樣
virtual ~Animal() = 0; //這是錯(cuò)的
看看正確的吧
{//類內(nèi)聲明
virtual ~Animal() = 0;
};
//類外定義
Animal::~Animal(){
cout << "Animal純虛析構(gòu)調(diào)用" << endl;
};
案例描述:
主要零件時(shí)CPU(用于計(jì)算),顯卡(用于顯示),內(nèi)存條(用于存儲(chǔ))
每個(gè)零件封裝成抽象基類,并且用于不同的廠商生產(chǎn)不同的零件
創(chuàng)建電腦類提供讓電腦工作的函數(shù),并且調(diào)用每個(gè)零件工作的接口
測(cè)試時(shí)組裝3臺(tái)不同的電腦工作
#include<iostream>
using namespace std;
class CPU{ //CPU類
public:
virtual void calculate() = 0;
};
class Card{ //顯卡類
public:
virtual void display() = 0;
};
class Memory{ //內(nèi)存條類
public:
virtual void storage() = 0;
};
class Com{ //電腦類
private:
CPU *m_cpu; //用指針來(lái)傳入三個(gè)零件數(shù)據(jù)(要用多態(tài)嘛)
Card *m_card;
Memory *m_memory;
public:
Com(CPU *cpu,Card *card,Memory *memory){ //有參構(gòu)造
m_cpu = cpu;
m_card = card;
m_memory = memory;
}
void work(){ //調(diào)用不同零件的函數(shù)
m_cpu->calculate();
m_card->display();
m_memory->storage();
}
//提供析構(gòu)函數(shù)來(lái)釋放三個(gè)零件
~Com(){
if(m_cpu != NULL){
delete m_cpu;
m_cpu = NULL;
}
if(m_card!= NULL){
delete m_card;
m_card = NULL;
}
if(m_memory != NULL){
delete m_memory;
m_memory = NULL;
}
}
};
//聯(lián)想廠商
class Lenovo:public CPU,public Card,public Memory{//方法一:三個(gè)子類再整合成一個(gè)大類,親測(cè)不太好用哎(我不知道該在怎么析構(gòu)比較好)
public:
void calculate(){
cout << "聯(lián)想的CPU開(kāi)始計(jì)算" << endl;
}
void display(){
cout << "聯(lián)想的顯卡開(kāi)始顯示" << endl;
}
void storage(){
cout << "聯(lián)想的內(nèi)存條開(kāi)始存儲(chǔ)" << endl;
}
};
//蘋(píng)果廠商
//方法二:把三個(gè)子類分開(kāi)
class AppleCPU:public CPU{ //簡(jiǎn)單的繼承和函數(shù)的重寫(xiě)
public:
void calculate(){
cout << "蘋(píng)果的CPU開(kāi)始計(jì)算" << endl;
}
};
class AppleCard:public Card{
public:
void display(){
cout << "蘋(píng)果的顯卡開(kāi)始顯示" << endl;
}
};
class AppleMemory:public Memory{
public:
void storage(){
cout << "蘋(píng)果的內(nèi)存條開(kāi)始顯示" << endl;
}
};
//戴爾廠商
class DellCPU:public CPU{
public:
void calculate(){
cout << "戴爾的CPU開(kāi)始計(jì)算" << endl;
}
};
class DellCard:public Card{
public:
void display(){
cout << "戴爾的顯卡開(kāi)始顯示" << endl;
}
};
class DellMemory:public Memory{
public:
void storage(){
cout << "戴爾的內(nèi)存條開(kāi)始顯示" << endl;
}
};
void test01(){
// Lenovo *lenovo = new Lenovo; 不寫(xiě)那個(gè)析構(gòu)的內(nèi)容的化,我感覺(jué)是對(duì)的,但有一點(diǎn)怪怪的
// Com *com = new Com(lenovo,lenovo,lenovo);
// com->work();
// //delete com;
// delete lenovo;
Com *com1 = new Com(new AppleCPU,new AppleCard,new AppleMemory); //使用了第二中的廠商法
com1->work();
delete com1;//delete的時(shí)候就調(diào)用析構(gòu)函數(shù)啦
cout << "=======================" << endl;
Com *com2 = new Com(new DellCPU,new AppleCard,new DellMemory); //使用了第二中的廠商法
com2->work();
delete com2;
}
int main(){
test01();
return 0;
}
本文名稱:C++基礎(chǔ)-類與對(duì)象(3)
網(wǎng)站鏈接:http://chinadenli.net/article34/dsoippe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開(kāi)發(fā)、、App設(shè)計(jì)、App開(kāi)發(fā)、手機(jī)網(wǎng)站建設(shè)、搜索引擎優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)