C++中包裝器的使用示例
在 C++ 中,包裝器(Wrapper) 也常被稱(chēng)為適配器(Adapter),是一種設(shè)計(jì)模式(結(jié)構(gòu)型模式)的實(shí)現(xiàn)——核心作用是包裝一個(gè)已有對(duì)象(或函數(shù)、指針等),轉(zhuǎn)換其接口、隱藏實(shí)現(xiàn)細(xì)節(jié),或增強(qiáng)其功能,讓原本不兼容的接口能夠協(xié)同工作,同時(shí)不改變?cè)瓕?duì)象的邏輯。
包裝器的核心價(jià)值:解耦、復(fù)用、接口統(tǒng)一。它就像一個(gè)“翻譯官”,讓兩個(gè)原本無(wú)法直接溝通的組件(如不同接口的類(lèi)、不同格式的函數(shù))能夠正常交互。
一、C++ 中常見(jiàn)的包裝器類(lèi)型
C++ 標(biāo)準(zhǔn)庫(kù)提供了多種內(nèi)置包裝器,同時(shí)也支持自定義包裝器。按包裝對(duì)象的不同,主要分為以下幾類(lèi):
1. 函數(shù)包裝器(std::function)
最常用的包裝器,用于包裝任意可調(diào)用對(duì)象(函數(shù)指針、lambda 表達(dá)式、函數(shù)對(duì)象、類(lèi)成員函數(shù)等),統(tǒng)一其調(diào)用接口。
核心用途:
- 消除可調(diào)用對(duì)象的類(lèi)型差異,實(shí)現(xiàn)“類(lèi)型擦除”(例如,不同簽名的函數(shù)統(tǒng)一用
std::function存儲(chǔ)); - 作為回調(diào)函數(shù)的統(tǒng)一載體(如 GUI 事件回調(diào)、異步任務(wù)回調(diào))。
語(yǔ)法與示例:
#include <functional>
#include <iostream>
// 普通函數(shù)
int add(int a, int b) { return a + b; }
// 函數(shù)對(duì)象(仿函數(shù))
struct Multiply {
int operator()(int a, int b) { return a * b; }
};
// 類(lèi)成員函數(shù)
class Calculator {
public:
int subtract(int a, int b) { return a - b; }
};
int main() {
// 包裝普通函數(shù)
std::function<int(int, int)> func1 = add;
std::cout << func1(2, 3) << std::endl; // 輸出 5
// 包裝函數(shù)對(duì)象
std::function<int(int, int)> func2 = Multiply{};
std::cout << func2(2, 3) << std::endl; // 輸出 6
// 包裝 lambda 表達(dá)式
std::function<int(int, int)> func3 = [](int a, int b) { return a / b; };
std::cout << func3(6, 2) << std::endl; // 輸出 3
// 包裝類(lèi)成員函數(shù)(需綁定實(shí)例)
Calculator calc;
std::function<int(int, int)> func4 = std::bind(&Calculator::subtract, &calc, std::placeholders::_1, std::placeholders::_2);
std::cout << func4(5, 2) << std::endl; // 輸出 3
return 0;
}
關(guān)鍵說(shuō)明:
std::function的模板參數(shù)是函數(shù)簽名(返回值類(lèi)型 + 參數(shù)類(lèi)型列表);- 支持拷貝、賦值,可作為容器元素(如
std::vector<std::function<int(int)>>); - 空的
std::function調(diào)用會(huì)拋出std::bad_function_call異常。
2. 指針包裝器(智能指針:std::unique_ptr/std::shared_ptr)
智能指針是裸指針的包裝器,核心作用是自動(dòng)管理內(nèi)存(避免內(nèi)存泄漏),同時(shí)提供與裸指針兼容的接口(如 operator*、operator->)。
核心用途:
- 替代裸指針,實(shí)現(xiàn)“資源自動(dòng)釋放”(RAII 機(jī)制);
- 隱藏內(nèi)存管理細(xì)節(jié)(如引用計(jì)數(shù)、獨(dú)占所有權(quán))。
示例:
#include <memory>
#include <iostream>
class MyClass {
public:
MyClass() { std::cout << "MyClass 構(gòu)造" << std::endl; }
~MyClass() { std::cout << "MyClass 析構(gòu)" << std::endl; }
void show() { std::cout << "Hello MyClass" << std::endl; }
};
int main() {
// std::unique_ptr:獨(dú)占所有權(quán)
std::unique_ptr<MyClass> ptr1 = std::make_unique<MyClass>();
ptr1->show(); // 接口與裸指針一致
// std::shared_ptr:共享所有權(quán)(引用計(jì)數(shù))
std::shared_ptr<MyClass> ptr2 = std::make_shared<MyClass>();
std::shared_ptr<MyClass> ptr3 = ptr2; // 引用計(jì)數(shù)+1
ptr3->show();
// 無(wú)需手動(dòng) delete,作用域結(jié)束時(shí)自動(dòng)析構(gòu)
return 0;
}
關(guān)鍵說(shuō)明:
- 智能指針是“資源包裝器”,遵循 RAII(資源獲取即初始化)原則;
- 包裝了裸指針的“內(nèi)存管理”邏輯,但對(duì)外提供與裸指針兼容的接口,不改變?cè)?lèi)的使用方式。
3. 迭代器適配器(std::reverse_iterator/std::insert_iterator等)
迭代器適配器是原生迭代器的包裝器,用于轉(zhuǎn)換迭代器的行為(如反向遍歷、插入元素而非覆蓋),讓同一容器支持不同的遍歷/操作方式。
常見(jiàn)類(lèi)型:
std::reverse_iterator:反向迭代器(包裝正向迭代器,實(shí)現(xiàn)反向遍歷);std::insert_iterator:插入迭代器(包裝容器迭代器,實(shí)現(xiàn)“插入”而非“覆蓋”賦值);std::back_insert_iterator/std::front_insert_iterator:尾部/頭部插入迭代器。
示例(反向迭代器):
#include <vector>
#include <iostream>
#include <iterator> // 包含迭代器適配器
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// 正向遍歷
std::cout << "正向遍歷:";
for (auto it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << " "; // 輸出 1 2 3 4 5
}
std::cout << std::endl;
// 反向遍歷(使用 reverse_iterator 包裝 begin()/end())
std::cout << "反向遍歷:";
for (auto it = std::reverse_iterator(vec.end()); it != std::reverse_iterator(vec.begin()); ++it) {
std::cout << *it << " "; // 輸出 5 4 3 2 1
}
std::cout << std::endl;
return 0;
}
關(guān)鍵說(shuō)明:
- 迭代器適配器不改變?nèi)萜鞯拇鎯?chǔ)結(jié)構(gòu),僅包裝迭代器的
operator++/operator*等行為; - 對(duì)外提供統(tǒng)一的迭代器接口(如
++、*),用戶(hù)無(wú)需關(guān)心底層實(shí)現(xiàn)差異。
4. 函數(shù)適配器(std::bind/std::not_fn)
函數(shù)適配器用于包裝可調(diào)用對(duì)象,修改其參數(shù)列表或邏輯(如綁定參數(shù)、取反邏輯),生成新的可調(diào)用對(duì)象。
(1)std::bind:參數(shù)綁定適配器
核心作用:綁定可調(diào)用對(duì)象的部分參數(shù),生成參數(shù)更少的新函數(shù)。
示例:
#include <functional>
#include <iostream>
int add(int a, int b, int c) { return a + b + c; }
int main() {
// 綁定第一個(gè)參數(shù)為 10,生成新函數(shù):int(int, int)
auto add10 = std::bind(add, 10, std::placeholders::_1, std::placeholders::_2);
std::cout << add10(2, 3) << std::endl; // 10+2+3=15
// 綁定后兩個(gè)參數(shù)為 5、6,生成新函數(shù):int(int)
auto add56 = std::bind(add, std::placeholders::_1, 5, 6);
std::cout << add56(4) << std::endl; // 4+5+6=15
return 0;
}
(2)std::not_fn:邏輯取反適配器
核心作用:包裝返回布爾值的可調(diào)用對(duì)象,生成“邏輯取反”的新函數(shù)(C++17 引入)。
示例:
#include <functional>
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// 查找偶數(shù)(原邏輯:x % 2 == 0)
auto even = [](int x) { return x % 2 == 0; };
auto it1 = std::find_if(vec.begin(), vec.end(), even);
std::cout << "第一個(gè)偶數(shù):" << *it1 << std::endl; // 輸出 2
// 查找奇數(shù)(包裝 even,邏輯取反)
auto odd = std::not_fn(even);
auto it2 = std::find_if(vec.begin(), vec.end(), odd);
std::cout << "第一個(gè)奇數(shù):" << *it2 << std::endl; // 輸出 1
return 0;
}
5. 自定義包裝器(類(lèi)適配器)
除了標(biāo)準(zhǔn)庫(kù)提供的包裝器,也可以手動(dòng)實(shí)現(xiàn)類(lèi)級(jí)別的包裝器,用于適配不同接口的類(lèi)。
場(chǎng)景:
假設(shè)已有一個(gè)舊接口的類(lèi) OldInterface,新代碼需要使用統(tǒng)一的 NewInterface 接口,此時(shí)可通過(guò)包裝器適配。
示例:
#include <iostream>
#include <string>
// 舊接口(無(wú)法修改)
class OldInterface {
public:
void do_old_task(const std::string& msg) {
std::cout << "舊接口執(zhí)行任務(wù):" << msg << std::endl;
}
};
// 新接口(統(tǒng)一規(guī)范)
class NewInterface {
public:
virtual ~NewInterface() = default;
virtual void execute(const std::string& task) = 0;
};
// 包裝器(適配器):將 OldInterface 適配為 NewInterface
class OldToNewAdapter : public NewInterface {
private:
OldInterface old_obj; // 包裝舊接口對(duì)象
public:
void execute(const std::string& task) override {
// 轉(zhuǎn)換接口:新接口的 execute 調(diào)用舊接口的 do_old_task
old_obj.do_old_task("適配后:" + task);
}
};
// 新代碼使用統(tǒng)一接口
void use_new_interface(NewInterface& obj) {
obj.execute("完成數(shù)據(jù)處理");
}
int main() {
OldToNewAdapter adapter;
use_new_interface(adapter); // 輸出:舊接口執(zhí)行任務(wù):適配后:完成數(shù)據(jù)處理
return 0;
}
關(guān)鍵說(shuō)明:
- 自定義包裝器通常采用“組合”(包裝被適配對(duì)象)或“繼承”(適配接口)的方式;
- 核心是“接口轉(zhuǎn)換”:對(duì)外提供目標(biāo)接口,對(duì)內(nèi)調(diào)用被包裝對(duì)象的原有接口。
二、包裝器的核心特性
- 接口轉(zhuǎn)換:將被包裝對(duì)象的接口轉(zhuǎn)換為目標(biāo)接口(如
OldInterface→NewInterface); - 透明性:用戶(hù)無(wú)需關(guān)心被包裝對(duì)象的細(xì)節(jié),僅需使用包裝器提供的統(tǒng)一接口;
- 增強(qiáng)功能:可在包裝器中添加額外邏輯(如日志、緩存、權(quán)限校驗(yàn)),不修改原對(duì)象;
- 復(fù)用性:同一包裝器可適配多個(gè)同類(lèi)被包裝對(duì)象(如
std::function可包裝任意符合簽名的可調(diào)用對(duì)象)。
三、包裝器與裝飾器的區(qū)別(易混淆點(diǎn))
很多人會(huì)將包裝器(適配器)與裝飾器(Decorator)混淆,兩者核心差異在于目的不同:
- 「包裝器(適配器)」:核心是接口適配(讓不兼容的接口協(xié)同工作);
- 「裝飾器」:核心是功能增強(qiáng)(在不改變接口的前提下,動(dòng)態(tài)添加新功能)。
示例區(qū)別:
- 適配器:將
OldInterface::do_old_task適配為NewInterface::execute(接口變了); - 裝飾器:給
NewInterface::execute增加日志功能(接口不變,功能變了)。
總結(jié)
C++ 中的包裝器(適配器)是“接口轉(zhuǎn)換與復(fù)用”的核心工具,分為:
- 標(biāo)準(zhǔn)庫(kù)內(nèi)置包裝器:
std::function(函數(shù))、智能指針(指針)、迭代器適配器(迭代器)、std::bind(函數(shù)參數(shù)); - 自定義包裝器:類(lèi)級(jí)別的接口適配。
其核心價(jià)值是解耦(隔離不同接口的組件)、復(fù)用(無(wú)需修改原有代碼)、統(tǒng)一接口(降低使用成本),是 C++ 中實(shí)現(xiàn)靈活設(shè)計(jì)的重要手段。
到此這篇關(guān)于C++中包裝器的使用示例的文章就介紹到這了,更多相關(guān)C++ 包裝器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++中l(wèi)ist實(shí)現(xiàn)雙向循環(huán)鏈表詳細(xì)解析
雙向循環(huán)鏈表是一種重要的線(xiàn)性數(shù)據(jù)結(jié)構(gòu),支持前后雙向遍歷,適用于頻繁插入刪除和高效訪(fǎng)問(wèn)的場(chǎng)景,這篇文章主要介紹了C++中l(wèi)ist實(shí)現(xiàn)雙向循環(huán)鏈表詳細(xì)解析的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2026-01-01
c++實(shí)現(xiàn)通用參數(shù)解析類(lèi)示例
使用命令行執(zhí)行程序的時(shí)候在程序后可跟多個(gè)參數(shù)列表,而main函數(shù)的argc和argv分別存儲(chǔ)了相關(guān)的參數(shù)個(gè)數(shù)和參數(shù)內(nèi)容,而循環(huán)輸入相關(guān)的時(shí)候就需要用戶(hù)自己來(lái)解析相關(guān)參數(shù)。以下代碼用c++的方式實(shí)現(xiàn)了相關(guān)解析的封裝,使用起來(lái)非常方便2014-03-03
C++之內(nèi)存分區(qū)的實(shí)現(xiàn)示例
本文主要介紹了C++之內(nèi)存分區(qū)的實(shí)現(xiàn)示例,主要包含了4個(gè)區(qū)域,分為代碼區(qū),全局區(qū),棧區(qū)和堆區(qū),文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-03-03
FFRPC應(yīng)用 Client/Server使用及原理解析
這篇文章主要介紹了FFRPC應(yīng)用 Client/Server使用及原理解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08
詳解C++編程中的嵌套類(lèi)的聲明與其中的函數(shù)使用
這篇文章主要介紹了C++編程中的嵌套類(lèi)的聲明與其中的函數(shù)使用,嵌套類(lèi)即在一個(gè)類(lèi)的范圍內(nèi)聲明和編寫(xiě)另一個(gè)類(lèi),需要的朋友可以參考下2016-01-01
文件編譯時(shí)出現(xiàn)multiple definition of ''xxxxxx''的具體解決方法
以下是對(duì)文件編譯時(shí)出現(xiàn)multiple definition of 'xxxxxx'的解決方法進(jìn)行了詳細(xì)的分析介紹,如也遇到此問(wèn)題的朋友們可以過(guò)來(lái)參考下2013-07-07
C++將二叉樹(shù)轉(zhuǎn)為雙向鏈表及判斷兩個(gè)鏈表是否相交
這篇文章主要介紹了C++將二叉樹(shù)轉(zhuǎn)為雙向鏈表及判斷兩個(gè)鏈表是否相交的方法,文中還給出了求兩個(gè)鏈表相交的第一個(gè)節(jié)點(diǎn)列的實(shí)現(xiàn)方法,需要的朋友可以參考下2016-02-02

