C++特性之多态,三个多态案例
生活随笔
收集整理的這篇文章主要介紹了
C++特性之多态,三个多态案例
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
多態
多態的基本概念
多態是C++面向對象三大特性之一
多態分為兩類
靜態多態:函數重載 和 運算符重載 屬于 靜態多態,復用函數名
動態多態:派生類 和 虛函數 實現運行時多態
靜態多態和動態多態區別:
(1)靜態多態的函數地址早綁定? –? 編譯階段確定函數地址
(2)動態多態的函數地址晚綁定? –? 運行階段確定函數地址
下面通過案例進行講解多態
#include<iostream>
using namespace std;//多態
class Animal{? ??
public:virtual?void speak(){?? ?//加上virtual后,函數變為虛函數cout << "動物在說話" << endl;}
};
class Cat :: public Animal{
public:void speak(){cout << "小貓在說話" << endl;}
}
18行:void doSpeak(Animal &animal){? ? //Animal &animal = cat??父類的引用在指向子類的對象//靜態多態animal.speak();? ? //這里調用的是父類的speak()函數,也就是動物在說話,因為這里函數的地址是早綁定的,也就是一開始就綁定了父類中的speak()函數,在編譯階段就確定了函數地址//如果想執行讓貓說話,那么這個函數地址就不能提前綁定,需要在運行階段進行綁定,地址晚綁定,解決方法,在speak()函數前加virtual,將函數更改為虛函數//動態多態animal.speak();? //這里就是貓在說話}
void test01(){Cat cat;doSpeak(cat);? ??
}
int main(){test01();system("pause") ;return 0;
}
總結:
動態多態滿足條件
1、有繼承關系
2、子類要重寫父類的虛函數(子類中重寫函數時可以不用加virtual,但是父類中必須加)
動態多態使用
父類的指針或者引用,執行子類對象(也就是第18行的代碼)
多態的底層原理:
#include<iostream>
using namespace std;//多態
class Animal{????
public:void speak(){????//加上virtual后,函數變為虛函數cout << "動物在說話" << endl;}
};
class Cat :: public Animal{
public:void speak(){cout << "小貓在說話" << endl;}
}
void doSpeak(Animal &animal){????//Animal &animal = cat??父類的引用在指向子類的對象animal.speak();? ?animal.speak();??
}
void test01(){Cat cat;doSpeak(cat);????
}
void test02(){cout << "sizeof Animal = " << sizeof(Animal) << endl; //現在Animal類中只有一個非靜態的成員函數,他不屬于類的對象,是分開存儲的,那Animal相當于是一個空類,那么他的大小就是sizeof(Animal) = 1;//如果加上virtual關鍵字,那么sizeof(Animal) = 4,這4個字節是一個指針,如圖1詳解
}
int main(){test01();test02();system("pause") ;return 0;
}
圖1
子類將父類拷貝一份之后speak函數的入口地址是Animal類中的speak函數地址,&Cat :: speak?這個代碼將speak函數的入口地址變為Cat對象的speak函數地址,然后會將原來子類中&Animal::speak函數的地址覆蓋掉,如下圖所示
這里就相當于子類將父類的虛函數給替換掉了,但是父類中的虛函數并沒有發生改變
當父類的指針或者引用指向子類對象的時候,發生多態
Animal *animal = cat ;
animal.speak();
由于指向的是一個cat對象,那么他會去cat的虛函數表中去找speak函數,這是在運行階段
?
多態案例一-計算器類
案例描述:
分別利用普通寫法和多態技術,設計實現兩個操作數進行運算的計算器類
多態的優點:
(1)代碼組織結構清晰
(2)可讀性強
(3)利于前期和后期的擴展以及維護
include<iostream>
using namespace std;//分別利用普通寫法和多態技術實現計算器
//普通寫法
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;}//如果想擴展新的功能,需要修改源碼int m_Num1 ;//操作數1int m_Num2;//操作數2
};void test01(){
//創建計算器對象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
}//利用多態實現計算器
//實現計算器抽象類
class AbstractCalculator
public:virtual?int getResult(){return 0;}int m_Num1;int m_Num2;
};
//加法計算器類
class AddCalculator : public AbstractCalculator{
public:virtual int getResult(){return m_Num1 + m_Num2;}
}
//減法計算器類
class SubCalculator : public AbstractCalculator{
public:virtual int getResult(){return m_Num1 - m_Num2;}
}
void test02(){//多態使用條件//父類指針或者引用指向子類對象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;
}
多態帶來的好處:
1、組織結構清晰
2、可讀性強
3、對于前期和后期擴展以及維護性高
案例三:
案例描述:
?? ??? ?電腦主要組成部件為CPU(用于計算),顯卡(用于顯示),內存條(用于存儲)
?? ??? ?將每個零件封裝出抽象基類,并且提供不同的廠商生產不同的零件,例如Intel廠商和Lenovo廠商創建電腦類提供讓電腦工作的函數,并且調用每個零件工作的接口
?? ??? ?測試時組裝三臺不同的電腦進行工作
#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; }總結
以上是生活随笔為你收集整理的C++特性之多态,三个多态案例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 自动超频_电脑超频有什么用?一键超频原来
- 下一篇: 一维激波C++编程