首先,不要使用reinterpret_cast
在与多态类的指针之间进行转换时。您可以编写一个简单的指针包装器,它允许您使用安全转换运算符static_cast
:
template <class Type>
class PointerWrapper
{
public:
PointerWrapper(Type* object);
PointerWrapper& operator=(Type* object);
Type* operator->();
protected:
Type* object;
};
template <class Type>
PointerWrapper<Type>::PointerWrapper(Type* object) :
object(object)
{
}
template <class Type>
PointerWrapper<Type>& PointerWrapper<Type>::operator=(Type* object)
{
this->object = object;
}
template <class Type>
Type* PointerWrapper<Type>::operator->()
{
return object;
}
现在你可以写:
typedef PointerWrapper<BaseVec> BaseVecPointer;
template<typename T>
double foo(void* p) {
BaseVecPointer* vp = static_cast<BaseVecPointer*>(p);
// ...
// ... = (*vp)->get_double(...);
// ...
return result;
}
在此代码中使用了多态性功能,即函数get_double
被调用而不是调用get
.
但如果你想打电话get
, not get_double
,即您想根据运行时变量的值调用具有不同模板参数的模板函数,可以使用以下方法:
enum FooTypes
{
NoFooType = -1,
DoubleFooType = 0,
IntegerFooType = 1,
// ...
FooTypesCount
};
template<FooTypes fooType>
struct ChooseType
{
static
const FooTypes value = NoFooType;
typedef void Type;
};
template<>
struct ChooseType<DoubleFooType>
{
static
const FooTypes value = DoubleFooType;
typedef double Type;
};
template<>
struct ChooseType<IntegerFooType>
{
static
const FooTypes value = IntegerFooType;
typedef int Type;
};
在这里您应该编写类模板的专业化ChooseType
对于所有可能的值type
多变的。
下面的代码描述了该功能ChooseFoo
选择什么专业foo_template
函数模板应该被调用:
typedef double (*FooFunction)(void*);
template<FooTypes fooType>
FooFunction ChooseFooImpl(int type)
{
if (type == fooType)
{
if (ChooseType<fooType>::value != NoFooType)
{
return foo_template<typename ChooseType<fooType>::Type>;
}
else
{
return NULL;
}
}
else
{
return ChooseFooImpl<(FooTypes)(fooType - 1)>(type);
}
}
template<>
FooFunction ChooseFooImpl<NoFooType>(int type)
{
return NULL;
}
FooFunction ChooseFoo(int type)
{
return ChooseFooImpl<FooTypesCount>(type);
}
这是foo
功能实现:
double foo(void* p, int type)
{
FooFunction fooFunction = ChooseFoo(type);
if (fooFunction != NULL)
{
return fooFunction(p);
}
else
{
//unsupported type
// ...
}
}