生活随笔
收集整理的這篇文章主要介紹了
C++(23)--多态性与虚函数
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
多態性與虛函數 1.靜態多態-重載 2.動態多態-重寫 3.虛函數的工作原理 4.純虛函數和抽象類 5.補充項目(都市浮生記)-卒
《老九學堂C++課程》學習筆記。《老九學堂C++課程》詳情請到B站搜索《老九零基礎學編程C++入門》
-------------簡單的事情重復做,重復的事情用心做,用心的事情堅持做(老九君)---------------
多態–多種表現形式,生物學名詞。 同一個名稱的函數,可以實現不同的功能。
什么是多態 面向對象編程的多態性包括: 1.面向不同的對象發送同一條信息–多個對象調用同一個函數 2.不同的對象在接收時回產生不同的行為– 不同的行為–不同的實現,即執行不同的函數功能。函數名相同,但執行的具體細節不同。
1.靜態多態-重載
靜態多態–重載 靜態多態也叫編譯時多態。 demo1.游戲引擎調用得中類對象進行移動操作
#ifndef CHAPTER14_GAMECORE_H
#define CHAPTER14_GAMECORE_H
#include <iostream>
#include <string>
#include <vector>
#include "Hero.h"
#include "Warrior.h"
#include "Archmage.h"
class GameCore {
public : GameCore ( ) ; ~ GameCore ( ) ; void MoveRole ( Warrior
& warrior
) { warrior
. Move ( ) ; } void MoveRole ( Archmage
& archmage
) { archmage
. Move ( ) ; } void MoveRole ( vector
< Warrior
* > vecWarrior
) { for ( auto warrior
: vecWarrior
) { warrior
- > Move ( ) ; } }
} ;
#endif
#include <iostream>
#include <string>
#include <vector>
#include "Hero.h"
#include "Warrior.h"
#include "Archmage.h"
#include "GameCore.h"
using namespace std
;
void HeroTest ( ) ;
int main ( ) { HeroTest ( ) ; return 0 ;
} void HeroTest ( ) { Hero
hero ( "布衣" ) ; Warrior
warrior1 ( "呂布1" , 50 ) ; Warrior
warrior2 ( "呂布2" , 50 ) ; Warrior
warrior3 ( "呂布3" , 50 ) ; Archmage
archmage ( "甘道夫" , 80 ) ; GameCore gamecore
;
vector
< Warrior
* > vecWarrior
; vecWarrior
. push_back ( & warrior1
) ; vecWarrior
. push_back ( & warrior2
) ; vecWarrior
. push_back ( & warrior3
) ; gamecore
. MoveRole ( vecWarrior
) ; }
輸出
調用了Hero 四個參數版本的構造
調用了Hero 一個參數版本的構造
調用了Hero 四個參數版本的構造
調用了Hero 四個參數版本的構造
調用了Hero 四個參數版本的構造
調用了Hero 四個參數版本的構造
戰士《呂布
1 》背著一大堆近戰武器正在前進。。。
戰士《呂布
2 》背著一大堆近戰武器正在前進。。。
戰士《呂布
3 》背著一大堆近戰武器正在前進。。。
2.動態多態-重寫
動態多態–重寫 動態多態也叫運行時多態,函數在執行的過程中才能確定要執行的是哪一個。
父類方法中加virtual關鍵字,在核心引擎類中的RoleMove參數使用hero 對象,那么可以給RoleMove傳遞各種hero子類實現各種移動。
#include <iostream>
#include <string>
#include <vector>
#include "Hero.h"
#include "Warrior.h"
#include "Archmage.h"
#include "GameCore.h"
#include "Assassin.h"
using namespace std
;
void HeroTest ( ) ;
int main ( ) { HeroTest ( ) ; return 0 ;
} void HeroTest ( ) { Hero
hero ( "布衣" ) ; Warrior
warrior1 ( "呂布1" , 50 ) ; Warrior
warrior2 ( "呂布2" , 50 ) ; Warrior
warrior3 ( "呂布3" , 50 ) ; Archmage
archmage ( "甘道夫" , 80 ) ; GameCore gamecore
; gamecore
. MoveRole ( warrior1
) ; gamecore
. MoveRole ( archmage
) ; Assassin
assa ( "飛檐走壁" , 100 ) ; gamecore
. MoveRole ( assa
) ;
}
新增的刺客類
#ifndef CHAPTER14_ASSASSIN_H
#define CHAPTER14_ASSASSIN_H
#include <iostream>
#include <string>
#include "Hero.h"
using namespace std
;
class Assassin : public Hero
{
public : Assassin ( ) ; Assassin ( const string
& nickName
, int power
) : Hero ( nickName
) , m_Power ( power
) { } void Move ( ) override
{ cout
<< "隱藏在黑暗中的刺客" << GetNickName ( ) << "正在偷偷地潛入一座宮殿" << endl
; } ~ Assassin ( ) ;
private : int m_Power
; } ; #endif
#include "Assassin.h" Assassin
:: Assassin ( ) { }
Assassin
:: ~ Assassin ( ) { }
2.1 向上轉換/向下轉換
3.虛函數的工作原理
1.構造函數不能是虛函數 2.析構函數應該定義成虛函數,除非該類不做基類。為了安全起見,為將類的析構函數定義為虛函數。 3.友元函數不能是虛函數。
虛函數的工作原理:會為父類對象構建一個隱藏成員,為指向虛函數表的指針。子類重寫了父類方法的話,也會為子類對象構建一個隱藏成員,為指向虛函數表的指針。但是具體的函數指針變了的。 demo1:觀察虛函數列表地址的變化(實驗現象沒有實現)
void VirtualPointTest ( ) {
Base base
; int * baseAdress
= ( int * ) & base
; cout
<< "基類對象地址" << baseAdress
<< endl
; int * virTablePtr
= ( int * ) * ( baseAdress
+ 0 ) ; cout
<< "基類隱藏成員:虛擬表的指針地址:" << virTablePtr
<< endl
;
cout
<< "第一個私有成員member的值:" << * ( baseAdress
+ 2 ) << endl
; cout
<< "---------- 派生類對象的內存信息如下----------------" << endl
; Son son
; int * sonAdress
= ( int * ) & son
; cout
<< "派生類對象的地址:" << sonAdress
<< endl
; virTablePtr
= ( int * ) * ( sonAdress
+ 0 ) ; cout
<< "派生類對象的虛擬表的地址:" << virTablePtr
<< endl
;
}
#ifndef CHAPTER14_VIRTUALPOINTDEMO1_H
#define CHAPTER14_VIRTUALPOINTDEMO1_H
#include <iostream>
#include <string>
using namespace std
;
class Base {
private : int menber
;
public : Base ( ) { menber
= 9527 ; } virtual void baseVirtual1 ( ) { cout
<< "基類中的虛函數版本1" << endl
; } virtual void baseVirtual2 ( ) { cout
<< "基類中的虛函數版本2" << endl
; } virtual void baseVirtual3 ( ) { cout
<< "基類中的虛函數版本3" << endl
; }
} ; class Son : public Base
{
public : void baseVirtual2 ( ) override
{ cout
<< "派生類中唯一實現的2版本的基類虛函數" << endl
; }
} ; #endif
4.純虛函數和抽象類
抽象類–天生的父類,實例出來沒啥用,需要進行擴展。(生物對象:血量,攻擊力)
語法上一個抽象類無法被實例化
抽象類的虛函數都為純虛函數,純虛函數讓基類函數沒有函數體,在基類中不能被調用。純虛函數必須有派生類來實現純虛函數體的功能。(一個類如果有一個純虛函數,那么這個類就是抽象類)
純虛函數語法格式
virtual 返回類型 函數名(參數列表) const=0;
demo:多態的方式來模擬“星際爭霸”中的指揮官和各種兵種之間的互動關系。 指揮官發出指令–Rolling Thunder,各單位發起進攻
#include <iostream>
#include <vector>
#include "AbstractClass.h" void AbstractTest ( ) ;
int main ( ) { AbstractTest ( ) ; return 0 ;
} void AbstractTest ( ) { Marin
marin1 ( "巫妖王" ) ; Marin
marin2 ( "死亡騎士" ) ; marin1
. Fight ( marin2
) ; SiegeTank
tank1 ( "坦克1" ) ; tank1
. Move ( 10 , 20 ) ; Viking
viking1 ( "北歐海盜" ) ; vector
< BattleUnit
* > units
; units
. push_back ( & marin1
) ; units
. push_back ( & marin2
) ; units
. push_back ( & tank1
) ; units
. push_back ( & viking1
) ; Commander commander
; cout
<< "讓指揮官移動多個不同類型的戰斗單位" << endl
; commander
. Move ( units
, 50 , 50 ) ;
}
#ifndef STAR_WAR_ABSTRACTCLASS_H
#define STAR_WAR_ABSTRACTCLASS_H
#include <iostream>
#include <string>
#include <vector>
using namespace std
;
class Point {
private : int m_x
; int m_y
;
public : Point ( ) { } Point ( int _x
, int _y
) : m_x ( _x
) , m_y ( _y
) { } int GetX ( ) { return m_x
; } int GetY ( ) { return m_y
; } void SetX ( int x
) { this - > m_x
= x
; } void SetY ( int y
) { this - > m_y
= y
; } friend ostream
& operator << ( ostream
& out
, const Point
& p
) { out
<< "(" << p
. m_x
<< "," << p
. m_y
<< ")" << endl
; return out
; }
} ; class BattleUnit {
private :
protected : string name
; int maxHp
; int currHp
; Point position
; int attDistance
;
public : BattleUnit ( ) { } BattleUnit ( const string
& _name
) : name ( _name
) { maxHp
= 100 ; currHp
= 100 ; position
. SetX ( 0 ) ; position
. SetY ( 0 ) ; attDistance
= 100 ; } virtual void Fight ( BattleUnit
& other
) = 0 ; virtual void Move ( int x
, int y
) = 0 ; virtual void Move ( Point
& position
) = 0 ; const string
& GetName ( ) const { return name
; }
} ;
void BattleUnit
:: Fight ( BattleUnit
& other
) { cout
<< name
<< "正在攻擊另一個戰斗單位:" << other
. GetName ( ) << endl
;
}
void BattleUnit
:: Move ( int x
, int y
) { position
. SetX ( x
) ; position
. SetX ( y
) ;
} class Marin : public BattleUnit
{
public : Marin ( ) { } Marin ( const string
& _name
) : BattleUnit ( _name
) { } void Fight ( BattleUnit
& other
) override
; void Move ( int x
, int y
) { BattleUnit
:: Move ( x
, y
) ; cout
<< "陸戰隊員接到命令,立即前往坐標點: " << position
<< endl
; } void Move ( Point
& position
) { }
} ;
void Marin
:: Fight ( BattleUnit
& other
) { BattleUnit
:: Fight ( other
) ; cout
<< "陸戰隊員" << GetName ( ) << "正在攻擊敵人:" << other
. GetName ( ) << endl
;
} class SiegeTank : public BattleUnit
{
public : SiegeTank ( ) { } SiegeTank ( const string
& _name
) : BattleUnit ( _name
) { } void Fight ( BattleUnit
& other
) override
{ } void Move ( int x
, int y
) override
{ position
. SetX ( x
) ; position
. SetY ( y
) ; cout
<< "工程坦克" << GetName ( ) << "收到移動命令:" << position
<< endl
; } void Move ( Point
& position
) override
{ }
} ;
class Viking : public BattleUnit
{
public : Viking ( ) { } Viking ( const string
& _name
) : BattleUnit ( _name
) { } void Fight ( BattleUnit
& other
) override
{ } void Move ( int x
, int y
) override
{ position
. SetX ( x
) ; position
. SetY ( y
) ; cout
<< "維京戰機" << GetName ( ) << "立即飛往坐標:" << position
<< endl
; } void Move ( Point
& position
) override
{ }
} ; class Commander {
public : void Move ( vector
< BattleUnit
* > units
, int x
, int y
) { for ( auto unit
: units
) { unit
- > Move ( x
, y
) ; } }
} ;
#endif 5.補充項目(都市浮生記)-卒
window 編程呀,mac 的頭文件都引入不了
總結
以上是生活随笔 為你收集整理的C++(23)--多态性与虚函数 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。