C++类型转换通用接口设计实现
目录
1.设计思路
2.通用转换接口实现
2.1.抽象基类(统一接口)
2.2.适配器子类(适配不同转换逻辑)
3.使用示例
4.统一接口调用(多转换器管理)
5.设计亮点
6.总结
1.设计思路
在 C++ 中设计通用类型转换接口的核心目标是:屏蔽不同类型、不同转换逻辑的差异,提供统一的转换入口 ,同时支持灵活扩展(如适配成员函数、全局函数、lambda 等转换逻辑)。基于类型擦除(Type Erasure) 和适配器模式,支持任意类型间的转换。
1.抽象接口层:定义统一的转换接口,作为所有转换器的基类,屏蔽具体类型细节。
2.适配器层:通过模板子类适配不同形式的转换逻辑(如成员函数、全局函数、lambda 等),负责具体类型的转换。
3.类型擦除:通过模板参数去适配各种不同的参数。
4.类型安全:在适配器中通过严格的类型转换确保输入 / 输出类型匹配,避免未定义行为。
2.通用转换接口实现
2.1.抽象基类(统一接口)
定义 AbstractConverterFunction作为所有转换器的基类,定义统一的转换方法,接收 void*
类型的输入和输出(实现类型擦除),在子类里面去实现这个转换方法。通过统一接口,可在代码中用 AbstractConverterFunction*
指针调用任意类型的转换,无需关心具体转换逻辑的实现细节。
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.适配器子类(适配不同转换逻辑)
针对不同形式的转换逻辑(成员函数、带校验的成员函数、函数对象等),实现对应的模板适配器子类,继承 AbstractConverterFunction
并实现 Convert
方法。
1.适配普通成员函数(From::toTo() const
)
当转换逻辑是 From
类的 const
成员函数,且无参数、返回 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;
};
- 核心作用:定义转换接口的 “外壳”,通过
Converter
函数指针存储具体的转换逻辑(由子类实现)。 - 类型擦除:基类本身不依赖模板参数,通过
void*
接收输入 / 输出数据,隐藏了具体的From
/To
类型,使得非模板代码可以统一使用AbstractConverterFunction*
调用转换。
2.适配带校验的成员函数(From::toTo(bool* ok) const
)
当转换可能失败(如字符串转数字),成员函数通过 bool*
输出成功标志时使用。
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;
};
- 适用场景:当转换逻辑是
From
类的一个const
成员函数,且该函数无参数、返回To
类型时(如class A { int toInt() const; };
,将A
转换为int
)。 - 工作原理:通过模板参数
From
/To
捕获具体类型,静态convert
方法负责将void*
安全转换为具体类型,再调用存储的成员函数完成转换。
3.适配函数对象(全局函数、lambda、std::function 等)
当转换逻辑是独立的可调用对象(输入 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;
};
- 适用场景:转换逻辑是独立的函数(非成员函数)、lambda 表达式或其他函数对象(如
std::function<To(From)>
)。 - 灵活性:支持任意可调用对象,例如
[](const std::string& s) { return s.size(); }
(将std::string
转换为size_t
)。
3.使用示例
假设我们有一个 String
类,需要转换为 int
或 size_t
,可以通过这套体系实现:
#include <string>
#include <cassert>// 示例类:String
class String {
private:std::string m_str;
public:String(std::string s) : m_str(std::move(s)) {}// 成员函数:转换为长度(size_t)size_t length() const { return m_str.size(); }// 带校验的成员函数:转换为 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(调用 length())ConverterMemberFunction<String, size_t> lenConverter(&String::length);String s1("hello");size_t len;// 调用转换:通过基类指针AbstractConverterFunction *converter = &lenConverter;bool ok = converter->convert(converter, &s1, &len);assert(ok && len == 5); // 成功,长度为5// 2. 使用 ConverterMemberFunctionOk:String → int(调用 toInt)ConverterMemberFunctionOk<String, int> intConverter(&String::toInt);String s2("123");int num;ok = intConverter.convert(&intConverter, &s2, &num);assert(ok && num == 123); // 转换成功String s3("abc"); // 无法转换为intok = intConverter.convert(&intConverter, &s3, &num);assert(!ok && num == 0); // 转换失败,num为默认值0// 3. 使用 ConverterFunctor:String → std::string(调用 lambda)auto strToStdStr = [](const String& s) { return static_cast<std::string>(s); // 假设String有转换运算符};ConverterFunctor<String, std::string, decltype(strToStdStr)> functorConverter(strToStdStr);std::string stdStr;ok = functorConverter.convert(&functorConverter, &s1, &stdStr);assert(ok && stdStr == "hello"); // 转换成功return 0;
}
4.统一接口调用(多转换器管理)
这套体系的核心价值是通过 AbstractConverterFunction*
统一管理不同类型的转换器,无需关心具体转换逻辑。例如在框架中存储多个转换器,动态调用:
#include <vector>int main() {// 创建多种转换器MyString s1("hello"), s2("123");std::string str("test");// 存储转换器指针(统一为 AbstractConverterFunction*)std::vector<AbstractConverterFunction*> converters;// 添加场景1的转换器(MyString → int,成员函数)converters.push_back(new ConverterMemberFunction<MyString, int>(&MyString::toInt));// 添加场景2的转换器(MyString → int,带校验)converters.push_back(new ConverterMemberFunctionOk<MyString, int>(&MyString::toInt));// 添加场景3的转换器(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));// 动态调用第一个转换器(MyString → int)int output1;converters[0]->convert(converters[0], &s1, &output1);std::cout << "转换器1结果:" << output1 << std::endl; // 5// 动态调用第二个转换器(带校验)int output2;converters[1]->convert(converters[1], &s2, &output2);std::cout << "转换器2结果:" << output2 << std::endl; // 123// 动态调用第三个转换器(string → size_t)size_t output3;converters[2]->convert(converters[2], &str, &output3);std::cout << "转换器3结果:" << output3 << std::endl; // 4// 释放内存for (auto c : converters) delete c;return 0;
}
5.设计亮点
1.类型擦除:通过基类 AbstractConverterFunction
屏蔽具体类型(From
/To
),使得非模板代码可以统一处理任意转换逻辑(只需存储 AbstractConverterFunction*
指针)。
2.多源适配:通过不同子类适配成员函数、带校验的成员函数、函数对象等多种转换源,覆盖大部分转换场景。
3.类型安全:虽然使用 void*
传递数据,但模板子类在 convert
方法中通过 static_cast
确保类型匹配(前提是使用时输入 / 输出类型与模板参数一致)。
4.轻量灵活:无需继承或虚函数重载,通过函数指针和模板封装转换逻辑,性能接近直接调用。
6.总结
这套代码是一个通用转换框架,核心通过 “抽象基类 + 模板子类 + 函数指针” 实现类型擦除,将不同形式的转换逻辑统一到同一接口下。适用于需要在运行时动态切换转换逻辑,或在非模板代码中处理多种类型转换的场景(如 Qt 的属性系统、数据绑定框架等)。使用时只需根据转换逻辑的类型(成员函数、带校验函数、lambda 等)选择对应的子类,即可通过基类指针统一调用。