C++類型轉(zhuǎn)換通用接口設(shè)計實現(xiàn)
1.設(shè)計思路
在 C++ 中設(shè)計通用類型轉(zhuǎn)換接口的核心目標(biāo)是:屏蔽不同類型、不同轉(zhuǎn)換邏輯的差異,提供統(tǒng)一的轉(zhuǎn)換入口 ,同時支持靈活擴(kuò)展(如適配成員函數(shù)、全局函數(shù)、lambda 等轉(zhuǎn)換邏輯)。基于類型擦除(Type Erasure) 和適配器模式,支持任意類型間的轉(zhuǎn)換。
1.抽象接口層:定義統(tǒng)一的轉(zhuǎn)換接口,作為所有轉(zhuǎn)換器的基類,屏蔽具體類型細(xì)節(jié)。
2.適配器層:通過模板子類適配不同形式的轉(zhuǎn)換邏輯(如成員函數(shù)、全局函數(shù)、lambda 等),負(fù)責(zé)具體類型的轉(zhuǎn)換。
3.類型擦除:通過模板參數(shù)去適配各種不同的參數(shù)。
4.類型安全:在適配器中通過嚴(yán)格的類型轉(zhuǎn)換確保輸入 / 輸出類型匹配,避免未定義行為。
2.通用轉(zhuǎn)換接口實現(xiàn)
2.1.抽象基類(統(tǒng)一接口)
定義 AbstractConverterFunction作為所有轉(zhuǎn)換器的基類,定義統(tǒng)一的轉(zhuǎn)換方法,接收 void* 類型的輸入和輸出(實現(xiàn)類型擦除),在子類里面去實現(xiàn)這個轉(zhuǎn)換方法。通過統(tǒng)一接口,可在代碼中用 AbstractConverterFunction* 指針調(diào)用任意類型的轉(zhuǎn)換,無需關(guān)心具體轉(zhuǎn)換邏輯的實現(xiàn)細(xì)節(jié)。
struct AbstractConverterFunction
{
typedef bool (*Converter)(const AbstractConverterFunction *, const void *, void*);
explicit AbstractConverterFunction(Converter c = nullptr)
: convert(c) {}
AbstractConverterFunction(const AbstractConverterFunction&)=delete;
AbstractConverterFunction& operator=(const AbstractConverterFunction&)=delete;
Converter convert;
};2.2.適配器子類(適配不同轉(zhuǎn)換邏輯)
針對不同形式的轉(zhuǎn)換邏輯(成員函數(shù)、帶校驗的成員函數(shù)、函數(shù)對象等),實現(xiàn)對應(yīng)的模板適配器子類,繼承 AbstractConverterFunction并實現(xiàn) Convert 方法。
1.適配普通成員函數(shù)(From::toTo() const)
當(dāng)轉(zhuǎn)換邏輯是 From 類的 const 成員函數(shù),且無參數(shù)、返回 To 類型時使用。
template<typename From, typename To>
struct ConverterMemberFunction : public AbstractConverterFunction
{
explicit ConverterMemberFunction(To(From::*function)() const)
: AbstractConverterFunction(convert),
m_function(function) {}
~ConverterMemberFunction();
static bool convert(const AbstractConverterFunction *_this, const void *in, void *out)
{
const From *f = static_cast<const From *>(in);
To *t = static_cast<To *>(out);
const ConverterMemberFunction *_typedThis =
static_cast<const ConverterMemberFunction *>(_this);
*t = (f->*_typedThis->m_function)();
return true;
}
To(From::* const m_function)() const;
};- 核心作用:定義轉(zhuǎn)換接口的 “外殼”,通過
Converter函數(shù)指針存儲具體的轉(zhuǎn)換邏輯(由子類實現(xiàn))。 - 類型擦除:基類本身不依賴模板參數(shù),通過
void*接收輸入 / 輸出數(shù)據(jù),隱藏了具體的From/To類型,使得非模板代碼可以統(tǒng)一使用AbstractConverterFunction*調(diào)用轉(zhuǎn)換。
2.適配帶校驗的成員函數(shù)(From::toTo(bool* ok) const)
當(dāng)轉(zhuǎn)換可能失敗(如字符串轉(zhuǎn)數(shù)字),成員函數(shù)通過 bool* 輸出成功標(biāo)志時使用。
template<typename From, typename To>
struct ConverterMemberFunctionOk : public AbstractConverterFunction
{
explicit ConverterMemberFunctionOk(To(From::*function)(bool *) const)
: AbstractConverterFunction(convert),
m_function(function) {}
~ConverterMemberFunctionOk();
static bool convert(const AbstractConverterFunction *_this, const void *in, void *out)
{
const From *f = static_cast<const From *>(in);
To *t = static_cast<To *>(out);
bool ok = false;
const ConverterMemberFunctionOk *_typedThis =
static_cast<const ConverterMemberFunctionOk *>(_this);
*t = (f->*_typedThis->m_function)(&ok);
if (!ok)
*t = To();
return ok;
}
To(From::* const m_function)(bool*) const;
};- 適用場景:當(dāng)轉(zhuǎn)換邏輯是
From類的一個const成員函數(shù),且該函數(shù)無參數(shù)、返回To類型時(如class A { int toInt() const; };,將A轉(zhuǎn)換為int)。 - 工作原理:通過模板參數(shù)
From/To捕獲具體類型,靜態(tài)convert方法負(fù)責(zé)將void*安全轉(zhuǎn)換為具體類型,再調(diào)用存儲的成員函數(shù)完成轉(zhuǎn)換。
3.適配函數(shù)對象(全局函數(shù)、lambda、std::function 等)
當(dāng)轉(zhuǎn)換邏輯是獨立的可調(diào)用對象(輸入 const From&,輸出 To)時使用。
template<typename From, typename To, typename UnaryFunction>
struct ConverterFunctor : public AbstractConverterFunction
{
explicit ConverterFunctor(UnaryFunction function)
: AbstractConverterFunction(convert),
m_function(function) {}
~ConverterFunctor();
static bool convert(const AbstractConverterFunction *_this, const void *in, void *out)
{
const From *f = static_cast<const From *>(in);
To *t = static_cast<To *>(out);
const ConverterFunctor *_typedThis =
static_cast<const ConverterFunctor *>(_this);
*t = _typedThis->m_function(*f);
return true;
}
UnaryFunction m_function;
};- 適用場景:轉(zhuǎn)換邏輯是獨立的函數(shù)(非成員函數(shù))、lambda 表達(dá)式或其他函數(shù)對象(如
std::function<To(From)>)。 - 靈活性:支持任意可調(diào)用對象,例如
[](const std::string& s) { return s.size(); }(將std::string轉(zhuǎn)換為size_t)。
3.使用示例
假設(shè)我們有一個 String 類,需要轉(zhuǎn)換為 int 或 size_t,可以通過這套體系實現(xiàn):
#include <string>
#include <cassert>
// 示例類:String
class String {
private:
std::string m_str;
public:
String(std::string s) : m_str(std::move(s)) {}
// 成員函數(shù):轉(zhuǎn)換為長度(size_t)
size_t length() const { return m_str.size(); }
// 帶校驗的成員函數(shù):轉(zhuǎn)換為 int(類似 QString::toInt)
int toInt(bool *ok) const {
try {
int val = std::stoi(m_str);
*ok = true;
return val;
} catch (...) {
*ok = false;
return 0;
}
}
};
int main() {
// 1. 使用 ConverterMemberFunction:String → size_t(調(diào)用 length())
ConverterMemberFunction<String, size_t> lenConverter(&String::length);
String s1("hello");
size_t len;
// 調(diào)用轉(zhuǎn)換:通過基類指針
AbstractConverterFunction *converter = &lenConverter;
bool ok = converter->convert(converter, &s1, &len);
assert(ok && len == 5); // 成功,長度為5
// 2. 使用 ConverterMemberFunctionOk:String → int(調(diào)用 toInt)
ConverterMemberFunctionOk<String, int> intConverter(&String::toInt);
String s2("123");
int num;
ok = intConverter.convert(&intConverter, &s2, &num);
assert(ok && num == 123); // 轉(zhuǎn)換成功
String s3("abc"); // 無法轉(zhuǎn)換為int
ok = intConverter.convert(&intConverter, &s3, &num);
assert(!ok && num == 0); // 轉(zhuǎn)換失敗,num為默認(rèn)值0
// 3. 使用 ConverterFunctor:String → std::string(調(diào)用 lambda)
auto strToStdStr = [](const String& s) {
return static_cast<std::string>(s); // 假設(shè)String有轉(zhuǎn)換運算符
};
ConverterFunctor<String, std::string, decltype(strToStdStr)> functorConverter(strToStdStr);
std::string stdStr;
ok = functorConverter.convert(&functorConverter, &s1, &stdStr);
assert(ok && stdStr == "hello"); // 轉(zhuǎn)換成功
return 0;
}4.統(tǒng)一接口調(diào)用(多轉(zhuǎn)換器管理)
這套體系的核心價值是通過 AbstractConverterFunction* 統(tǒng)一管理不同類型的轉(zhuǎn)換器,無需關(guān)心具體轉(zhuǎn)換邏輯。例如在框架中存儲多個轉(zhuǎn)換器,動態(tài)調(diào)用:
#include <vector>
int main() {
// 創(chuàng)建多種轉(zhuǎn)換器
MyString s1("hello"), s2("123");
std::string str("test");
// 存儲轉(zhuǎn)換器指針(統(tǒng)一為 AbstractConverterFunction*)
std::vector<AbstractConverterFunction*> converters;
// 添加場景1的轉(zhuǎn)換器(MyString → int,成員函數(shù))
converters.push_back(new ConverterMemberFunction<MyString, int>(&MyString::toInt));
// 添加場景2的轉(zhuǎn)換器(MyString → int,帶校驗)
converters.push_back(new ConverterMemberFunctionOk<MyString, int>(&MyString::toInt));
// 添加場景3的轉(zhuǎn)換器(string → size_t,lambda)
auto lambda = [](const std::string& s) { return s.size(); };
converters.push_back(new ConverterFunctor<std::string, size_t, decltype(lambda)>(lambda));
// 動態(tài)調(diào)用第一個轉(zhuǎn)換器(MyString → int)
int output1;
converters[0]->convert(converters[0], &s1, &output1);
std::cout << "轉(zhuǎn)換器1結(jié)果:" << output1 << std::endl; // 5
// 動態(tài)調(diào)用第二個轉(zhuǎn)換器(帶校驗)
int output2;
converters[1]->convert(converters[1], &s2, &output2);
std::cout << "轉(zhuǎn)換器2結(jié)果:" << output2 << std::endl; // 123
// 動態(tài)調(diào)用第三個轉(zhuǎn)換器(string → size_t)
size_t output3;
converters[2]->convert(converters[2], &str, &output3);
std::cout << "轉(zhuǎn)換器3結(jié)果:" << output3 << std::endl; // 4
// 釋放內(nèi)存
for (auto c : converters) delete c;
return 0;
}5.設(shè)計亮點
1.類型擦除:通過基類 AbstractConverterFunction 屏蔽具體類型(From/To),使得非模板代碼可以統(tǒng)一處理任意轉(zhuǎn)換邏輯(只需存儲 AbstractConverterFunction* 指針)。
2.多源適配:通過不同子類適配成員函數(shù)、帶校驗的成員函數(shù)、函數(shù)對象等多種轉(zhuǎn)換源,覆蓋大部分轉(zhuǎn)換場景。
3.類型安全:雖然使用 void* 傳遞數(shù)據(jù),但模板子類在 convert 方法中通過 static_cast 確保類型匹配(前提是使用時輸入 / 輸出類型與模板參數(shù)一致)。
4.輕量靈活:無需繼承或虛函數(shù)重載,通過函數(shù)指針和模板封裝轉(zhuǎn)換邏輯,性能接近直接調(diào)用。
6.總結(jié)
這套代碼是一個通用轉(zhuǎn)換框架,核心通過 “抽象基類 + 模板子類 + 函數(shù)指針” 實現(xiàn)類型擦除,將不同形式的轉(zhuǎn)換邏輯統(tǒng)一到同一接口下。適用于需要在運行時動態(tài)切換轉(zhuǎn)換邏輯,或在非模板代碼中處理多種類型轉(zhuǎn)換的場景(如 Qt 的屬性系統(tǒng)、數(shù)據(jù)綁定框架等)。使用時只需根據(jù)轉(zhuǎn)換邏輯的類型(成員函數(shù)、帶校驗函數(shù)、lambda 等)選擇對應(yīng)的子類,即可通過基類指針統(tǒng)一調(diào)用。
到此這篇關(guān)于C++類型轉(zhuǎn)換通用接口設(shè)計實現(xiàn)的文章就介紹到這了,更多相關(guān)C++類型轉(zhuǎn)換通用接口內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++中std::construct()與std::destroy()的使用
std::construct()和std::destroy()是C++ STL中的函數(shù)模板,用于在已分配的存儲區(qū)域中構(gòu)造或銷毀對象,本文主要介紹了C++中std::construct()與std::destroy()的使用,感興趣的可以了解一下2024-02-02
C/C++獲取當(dāng)前時間的方法總結(jié)(最全)
這篇文章主要為大家整理了C/C++中獲取當(dāng)前時間的最全方法,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)和借鑒價值,需要的可以了解一下2023-03-03
C++基于socket多線程實現(xiàn)網(wǎng)絡(luò)聊天室
這篇文章主要為大家詳細(xì)介紹了C++基于socket多線程實現(xiàn)網(wǎng)絡(luò)聊天室,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-07-07
C語言system 自動關(guān)機(jī)函數(shù)代碼
這篇文章主要介紹了C語言system 自動關(guān)機(jī)函數(shù)代碼,需要的朋友可以參考下2016-04-04

