C++虛函數(shù)和多態(tài)超詳細(xì)分析

1.什么是虛函數(shù)
C++類中用virtual修飾的函數(shù)叫做虛函數(shù),構(gòu)造函數(shù)沒(méi)有虛構(gòu)造函數(shù),存在虛析構(gòu)函數(shù),C++所有虛函數(shù)都是一個(gè)指針去存儲(chǔ)的,所以具有虛函數(shù)的類,內(nèi)存會(huì)增加一個(gè)指針大小的內(nèi)存
#include<iostream>
#include<string>
using namespace std;
class MM
{
public:
//虛函數(shù)指針是同一個(gè),所以無(wú)論該類中有多少個(gè)虛函數(shù),
//占用的內(nèi)存就只是一個(gè)指針的大小
virtual void print()
{
cout << "我是第一個(gè)虛函數(shù)" << endl;
}
virtual void printData()
{
cout << "我是第二個(gè)虛函數(shù)" << endl;
}
protected:
};
class son:public MM
{
public:
void print()
{
//該函數(shù)也是虛函數(shù),
//父類中同名函數(shù)是虛函數(shù)
//所以子類該函數(shù)也是虛函數(shù)
}
protected:
};
int main()
{
cout << sizeof(MM) << endl;
cout << "...................." << endl;
//虛函數(shù)表的理解,下面帶圖解
MM mm;
long long** p = (long long**)&mm;
using Func = void(*)();
Func f1 = (Func)p[0][0];
Func f2 = (Func)p[0][1];
f1();
f2();
return 0;
}

2.純虛函數(shù)
純虛函數(shù)也是虛函數(shù)的一種,只是沒(méi)有函數(shù)體,下面請(qǐng)看怎么表示沒(méi)有函數(shù)體
純虛函數(shù)——>虛函數(shù)=0;
具有一個(gè)或者多個(gè)虛函數(shù)的類叫做抽象類
- 抽象類不能構(gòu)建對(duì)象
- 但是可以構(gòu)建函數(shù)指針
#include<iostream>
using namespace std;
class MM
{
public:
virtual void print() = 0;
};
int main()
{
//MM mm; //抽象類不能構(gòu)建對(duì)象
MM* pmm = nullptr;
return 0;
}
3.c++多態(tài)
多態(tài)指的是因?yàn)橹羔樀牟煌馁x值操作所導(dǎo)致的同一行為的不同結(jié)果。多態(tài)的這個(gè)概念東西不太重要,重要的是什么樣的情況調(diào)用什么樣的行為
- 正常指針和正常對(duì)象調(diào)用行為,就近原則
- 父類指針被子類對(duì)象初始化
- 函數(shù)有
virtual看對(duì)象類型 - 函數(shù)沒(méi)有
virtual看指針類型 final關(guān)鍵字 禁止子類重寫(xiě)父類方法override顯示說(shuō)明當(dāng)前函數(shù)是重寫(xiě)函數(shù)
多態(tài)三個(gè)必要性條件:
- 父類中存在虛函數(shù)
- 存在不正常指針的引用(不正常賦值關(guān)系)
public繼承
#include<iostream>
using namespace std;
class MM
{
public:
void print()
{
cout << "父類" << endl;
}
virtual void printData()
{
cout << "MM" << endl;
}
};
class son :public MM
{
public:
void print()
{
cout << "子類" << endl;
}
void printData()
{
cout << "son" << endl;
}
};
int main()
{
MM* pmm = new son;
pmm->print();
pmm->printData();
return 0;
}
4.純虛函數(shù)和ADT過(guò)程
ADT:abstract data type抽象數(shù)據(jù)類型,主要是通過(guò)繼承抽象類中,子類必須要實(shí)現(xiàn)父類的抽象方法,子類才可以創(chuàng)建對(duì)象。
#include<iostream>
#include<string>
using namespace std;
class data
{
public:
string name;
int age;
};
class MM
{
public:
virtual bool empty() = 0;
virtual int size() = 0;
};
class List:public MM
{
public:
bool empty()
{
return 0;
}
int size()
{
return NULL;
}
};
int main()
{
MM* pmm = new List;
pmm->empty();
pmm->size();
}
5.虛析構(gòu)函數(shù)
virtual修飾的析構(gòu)函數(shù)就是虛析構(gòu)函數(shù),當(dāng)存在子類對(duì)象初始化父類指針的時(shí)候,父類析構(gòu)函數(shù)就要是虛析構(gòu)函數(shù),否則只會(huì)釋放父類,存在內(nèi)存泄漏問(wèn)題
#include<iostream>
using namespace std;
class MM
{
public:
virtual ~MM()
{
cout << "父類" << endl;
}
};
class son:public MM
{
public:
~son()
{
cout << "子類" << endl;
}
};
int main()
{
MM* pmm = new son;
delete pmm;
return 0;
}
6.dynamic_cast類型轉(zhuǎn)換
- 上行轉(zhuǎn)換 子類到父類 和
staic_cast差不多 - 下行轉(zhuǎn)換 父類到子類
dynamic_cast更為安全 - 交叉轉(zhuǎn)換 多繼承
#include<iostream>
using namespace std;
class MM
{
public:
virtual void print() { cout << "MM" << endl; }
};
class son:public MM
{
public:
void print() { cout << "son" << endl; }
};
class A
{
public:
virtual void print(){}
};
class B
{
public:
virtual void print() {}
};
class C:public A,public B
{
public:
void print()
{
cout << "c" << endl;
}
};
int main()
{
MM* partent = new MM;
son* Son = new son;
//上行轉(zhuǎn)換----->沒(méi)有必要
MM* p = static_cast<MM*>(Son);
MM* pp = dynamic_cast<MM*>(Son);
MM* ppp = Son; //可以
//下行轉(zhuǎn)換
son* x = dynamic_cast<son*>(partent); //安全,父類沒(méi)有virtual會(huì)報(bào)錯(cuò)---->多態(tài)
if(!x)
{
printf("error");
} //下行轉(zhuǎn)換不安全,不會(huì)申請(qǐng)成功
A* a = new A;
B* b = dynamic_cast<B*>(a);
b->print();
return 0;
}

7.成員函數(shù)指針
#include<iostream>
#include<functional>
using namespace std;
class MM
{
public:
void print() { cout << "king" << endl; }
static void printData() { cout << "MM" << endl; }
};
int main()
{
void(*p)() = &MM::printData;
p();
//必須通過(guò)對(duì)象調(diào)用
void(MM::*pp)() = &MM::print;
MM mm;
(mm.*pp)();
//函數(shù)適配器,讓函數(shù)調(diào)用形態(tài)可以適用于別的形態(tài)
auto f = bind(&MM::print, &mm);
f();
return 0;
}
到此這篇關(guān)于C++虛函數(shù)和多態(tài)超詳細(xì)分析的文章就介紹到這了,更多相關(guān)C++虛函數(shù)和多態(tài)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
一起來(lái)學(xué)習(xí)C語(yǔ)言的輸入和輸出
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言的輸入和輸出,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-03-03
c語(yǔ)言:基于函數(shù)指針的兩個(gè)示例分析
本篇文章是對(duì)c語(yǔ)言中函數(shù)指針的兩個(gè)示例做了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
C語(yǔ)言實(shí)現(xiàn)二叉樹(shù)鏈?zhǔn)浇Y(jié)構(gòu)的示例詳解
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)二叉樹(shù)鏈?zhǔn)浇Y(jié)構(gòu)的相關(guān)資料,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C語(yǔ)言有一定的幫助,需要的可以參考一下2022-11-11
C語(yǔ)言之結(jié)構(gòu)體定義 typedef struct 用法詳解和用法小結(jié)
這篇文章主要介紹了C語(yǔ)言的結(jié)構(gòu)體定義typedef struct用法詳解和用法小結(jié),typedef是類型定義,typedef struct 是為了使用這個(gè)結(jié)構(gòu)體方便,感興趣的同學(xué)可以參考閱讀2023-03-03
Cocos2d-x 3.x入門教程(二):Node節(jié)點(diǎn)類
這篇文章主要介紹了Cocos2d-x 3.x入門教程(二):Node節(jié)點(diǎn)類,本文對(duì)Node節(jié)點(diǎn)類做了一個(gè)簡(jiǎn)明講解及Node類提供的函數(shù)做了說(shuō)明,需要的朋友可以參考下2014-11-11
C++中拷貝構(gòu)造函數(shù)的應(yīng)用詳解
這篇文章主要介紹了C++中拷貝構(gòu)造函數(shù)的應(yīng)用,需要的朋友可以參考下2014-07-07

