这次我们要用垫片类实现一个C++不直接支持的语法:根据返回值重载函数。
首先有以下两个函数
int GetValueInt(const void* ptr); { return *(const int*)ptr; }
float GetValueFloat(const void* ptr); { return *(const float*)ptr; }
功能是按照指定类型从某块内存中读取数据。
我们的目标是实现
int i = GetValue(ptr); //调用GetValueInt
float f = GetValue(ptr); //调用GetValueFloat
C++在重载函数时要求参数必须不同,因此上述目标是无法直接实现的。只能通过别的方法间接实现。
方式一,模板
通过模板的特化功能来指定不同返回值时的函数调用,不过在调用时仍然需要显式指定返回值类型。
template<typename type_t>
type_t GetValue_V1(const void* ptr)
{
return type_t();
}
template<> int GetValue_V1<int>(const void* ptr)
{
return GetValueInt(ptr);
}
template<> float GetValue_V1<float>(const void* ptr)
{
return GetValueFloat(ptr);
}
int i = GetValue_V1<int>(ptr); //调用GetValueInt
float f = GetValue_V1<float>(ptr); //调用GetValueFloat
方式二, 参数提示
将返回值类型作为额外参数传递给函数,该参数虽然在函数实现中没有用,但是在函数调用时能够区别出不同函数。
int GetValue_V2(const void* ptr, int)
{
return GetValueInt(ptr);
}
float GetValue_V2(const void* ptr,float)
{
return GetValueFloat(ptr);
}
int i = GetValue_V2(ptr, 1); //调用GetValueInt
float f = GetValue_V2(ptr, 1.0f); //调用GetValueFloat
方式三,垫片类
在调用时不直接调用内存读取函数,而是把参数构造成一个垫片类并返回。然后垫片类会根据最终的数据类型调用不同的运算符重载函数,此时才进行内存读取。
class cGetValueShim
{
public:
cGetValueShim(const void* ptr) : m_ptr(ptr) {}
operator int() const { return GetValueInt(m_ptr); }
operator float() const { return GetValueFloat(m_ptr); }
private:
const void* m_ptr;
};
cGetValueShim GetValue_V3(const void* ptr)
{
return cGetValueShim(ptr);
}
int i = GetValue_V3(ptr); //调用GetValueInt
float f = GetValue_V3(ptr); //调用GetValueFloat