手寫 C++ Any 類:深入理解多態(tài)與模板(示例詳解)
我們自己實(shí)現(xiàn)的閹割版 Any 類核心能力:用一個(gè)類存儲(chǔ)任意類型數(shù)據(jù)(int/自定義類/字符串等),底層依靠 抽象基類+模板子類 實(shí)現(xiàn)類型擦除。
模塊1:頭文件包含
#include <iostream> // 輸入輸出 #include <typeinfo> // 類型識(shí)別:typeid 運(yùn)算符核心依賴 #include <utility> // 標(biāo)準(zhǔn)庫(kù) swap 函數(shù) #include <cassert> // 斷言:類型不匹配時(shí)報(bào)錯(cuò)
講解
這四個(gè)頭文件是實(shí)現(xiàn) Any 類的基礎(chǔ):
typeinfo:提供typeid,用于類型安全校驗(yàn);utility:提供std::swap,實(shí)現(xiàn)高效交換;cassert:斷言,防止非法類型獲取數(shù)據(jù),保證程序安全。
模塊2:內(nèi)部抽象基類holder(類型擦除核心接口)
class holder
{
public:
virtual ~holder(){} // 虛析構(gòu)函數(shù)
virtual const std::type_info& type() =0; // 純虛函數(shù):獲取類型
virtual holder* clone()=0; // 純虛函數(shù):克隆對(duì)象
};講解
- 定位:
Any類的私有內(nèi)部抽象類,對(duì)外完全隱藏; - 虛析構(gòu):必須加!保證多態(tài)刪除子類對(duì)象時(shí),析構(gòu)函數(shù)能被正確調(diào)用,防止內(nèi)存泄漏;
- 純虛函數(shù):
type():返回存儲(chǔ)數(shù)據(jù)的類型信息;clone():深拷貝對(duì)象,支持Any的拷貝/賦值;
- 作用:定義統(tǒng)一接口,屏蔽具體類型差異,是類型擦除的基石。
模塊3:模板子類placeholder<T>(真正存儲(chǔ)數(shù)據(jù)的地方)
template<class T>
class placeholder:public holder
{
public:
placeholder(const T&val):_val(val){}
virtual const std::type_info& type(){return typeid(T);}
virtual holder* clone(){return new placeholder(_val);}
public:
T _val; // 真實(shí)存儲(chǔ)數(shù)據(jù)的變量
};
講解
- 模板類:
T是任意類型(int/Test/string…),真正實(shí)現(xiàn)存儲(chǔ)任意數(shù)據(jù); - 繼承
holder:滿足多態(tài)要求,對(duì)外統(tǒng)一表現(xiàn)為holder類型; - 構(gòu)造函數(shù):初始化成員變量
_val,存入數(shù)據(jù); - 重寫純虛函數(shù):
type():返回當(dāng)前模板類型T的信息;clone():創(chuàng)建自身副本,實(shí)現(xiàn)深拷貝;
- 核心:
_val是真實(shí)數(shù)據(jù)存儲(chǔ)位置,外部完全不可見(jiàn)。
模塊4:Any類核心成員 + 構(gòu)造/析構(gòu)函數(shù)
holder*_content; // 核心指針
// 默認(rèn)構(gòu)造:空對(duì)象
Any():_content(nullptr){}
// 模板構(gòu)造函數(shù):接收任意類型數(shù)據(jù)
template<class T>
Any(const T&val):_content(new placeholder<T>(val)){}
// 拷貝構(gòu)造函數(shù):深拷貝
Any(const Any&other):_content(other._content?other._content->clone():nullptr)
{}
// 析構(gòu)函數(shù):自動(dòng)釋放內(nèi)存
~Any(){delete _content;}講解
- 核心成員
_content:holder基類指針,多態(tài)指向placeholder<T>子類對(duì)象,實(shí)現(xiàn)類型擦除; - 默認(rèn)構(gòu)造:創(chuàng)建空的
Any對(duì)象; - 模板構(gòu)造:接收任意類型
T,創(chuàng)建placeholder<T>對(duì)象并賦值給指針; - 拷貝構(gòu)造:調(diào)用
clone()實(shí)現(xiàn)深拷貝,避免淺拷貝指針懸空; - 析構(gòu)函數(shù):RAII 機(jī)制,自動(dòng)釋放內(nèi)存,無(wú)需手動(dòng)管理指針。
模塊5:交換函數(shù)swap(異常安全核心)
Any&swap(Any&other)
{
std::swap(_content,other._content);
return *this;
}講解
- 作用:避免自賦值,先構(gòu)造一個(gè)臨時(shí)對(duì)象,再交換交換兩個(gè)
Any對(duì)象的內(nèi)部指針; - 價(jià)值:是拷貝交換法的基礎(chǔ),讓賦值運(yùn)算符異常安全、無(wú)內(nèi)存泄漏、無(wú)需處理自賦值;
- 極簡(jiǎn)高效:僅交換指針,不拷貝數(shù)據(jù),性能極高。
模塊6:數(shù)據(jù)獲取函數(shù)get<T>()(類型安全)
template<class T>
T*get()
{
assert(typeid(T)==_content->type());
return &((placeholder<T>*)_content)->_val;
}講解
- 模板函數(shù):指定要獲取的類型
T; - 斷言校驗(yàn):類型不匹配直接終止程序,保證類型安全;
- 類型強(qiáng)轉(zhuǎn):將基類指針強(qiáng)轉(zhuǎn)為子類指針,獲取真實(shí)數(shù)據(jù)
_val; - 返回值:返回?cái)?shù)據(jù)指針,可讀寫內(nèi)部數(shù)據(jù)。
模塊7:賦值運(yùn)算符重載(兩種賦值方式)
// 賦值1:任意類型直接賦值給 Any
template<class T>
Any& operator=(const T&val)
{
Any(val).swap(*this);
return *this;
}
// 賦值2:Any 對(duì)象之間賦值
Any& operator=(const Any&other)
{
Any(other).swap(*this);
return *this;
}講解
- 統(tǒng)一用法:拷貝交換法,C++ 賦值運(yùn)算符最優(yōu)寫法;
- 原理:
① 先創(chuàng)建臨時(shí)對(duì)象Any(val)/Any(other);
② 交換臨時(shí)對(duì)象和當(dāng)前對(duì)象的指針;
③ 臨時(shí)對(duì)象析構(gòu),自動(dòng)釋放舊內(nèi)存; - 優(yōu)點(diǎn):避免自賦值問(wèn)題,異常安全, 無(wú)內(nèi)存泄漏,代碼極簡(jiǎn)
模塊8:測(cè)試類Test(驗(yàn)證生命周期)
class Test
{
public:
Test(){ std::cout<<"構(gòu)造"<<std::endl;}
Test(const Test&t){ std::cout<<"拷貝構(gòu)造"<<std::endl;}
~Test(){ std::cout<<"析構(gòu)"<<std::endl;}
};講解
自定義測(cè)試類,通過(guò)打印構(gòu)造/拷貝構(gòu)造/析構(gòu)日志,驗(yàn)證:
Any類能正常存儲(chǔ)自定義類型;- 內(nèi)存管理正確,無(wú)泄漏;
- 拷貝/賦值行為符合預(yù)期。
模塊9:主函數(shù)測(cè)試(功能驗(yàn)證)
int main()
{
Any a;
{
Test t;
a=t;
}
a=10;
int *pa=a.get<int>();
std::cout<<*pa<<std::endl;
return 0;
}講解
- 測(cè)試空對(duì)象初始化;
- 測(cè)試自定義類型賦值;
- 測(cè)試局部對(duì)象生命周期;
- 測(cè)試int 類型賦值 + 獲取數(shù)據(jù);
- 驗(yàn)證全程內(nèi)存自動(dòng)管理,無(wú)泄漏。
核心總結(jié)
- holder:抽象接口,定義統(tǒng)一規(guī)范;
- placeholder:模板子類,真正存數(shù)據(jù);
- _content:基類指針,多態(tài)+類型擦除核心;
- 拷貝交換法:賦值運(yùn)算符最優(yōu)解;
- RAII:構(gòu)造申請(qǐng)內(nèi)存,析構(gòu)自動(dòng)釋放。
到此這篇關(guān)于手寫 C++ Any 類:深入理解多態(tài)與模板(示例詳解)的文章就介紹到這了,更多相關(guān) C++ Any 類內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vs2019安裝及簡(jiǎn)單處理技巧(超詳細(xì))
這篇文章主要介紹了vs2019安裝及簡(jiǎn)單處理方法,本文是一篇非常詳細(xì)的教程,通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06
C++任意線程通過(guò)hwnd實(shí)現(xiàn)將操作發(fā)送到UI線程執(zhí)行
做Windows界面開發(fā)時(shí),經(jīng)常需要在多線程環(huán)境中將操作拋到主線程執(zhí)行,下面我們就來(lái)學(xué)習(xí)一下如何在不需要重新定義消息以及接收消息的情況下實(shí)現(xiàn)這一要求,感興趣的可以了解下2024-03-03
簡(jiǎn)單說(shuō)說(shuō)STL的內(nèi)存管理
c++中的字節(jié)序與符號(hào)位的問(wèn)題
C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單翻譯功能
C++多態(tài)特性之派生與虛函數(shù)與模板詳細(xì)介紹
C語(yǔ)言入門篇--四大常量(字面,const修飾,宏,枚舉)及標(biāo)識(shí)符

