首先,我想提一下,这适用于MSVC但不适用于clang。我正在使用Clang和c ++ 11。
我有一个函数指针:
typedef void (*Log) (const char* title, const char* msg, const char* file, int line);
我有这个结构:
struct FunctionList
{
protected:
static const int kNbrMax = 32;
FunctionList();
bool Add(const void* f);
bool Remove(const void* f);
const void* m_functions[kNbrMax];
};
这节课:
template<typename T>
struct MessageFunctionList
: public FunctionList
{
public:
MessageFunctionList(T defaultFunction)
{
Add(defaultFunction);
}
void Call(const char* title,const char* cause,const char* file,int line)
{
for (unsigned long i = 0;i < m_nbrUsed;++i)
{
reinterpret_cast<T>(m_functions[i])(title,cause,file,line);
}
}
}
我正在创建它:
static void DefaultLogMessageFunction(const char* title,const char* msg,const char* file,int line)
{
}
MessageFunctionList<Log> functionList(DefaultLogMessageFunction)
但是我得到编译时错误:
从'const void '到'void()的reinterpret_cast(const char *,const char *,const char *,int)'抛弃线的限定符: 的reinterpret_cast(m_functions [I])(标题,原因,文件,行);
据我所知,我试图将我的const函数列表转换为非const值。这是不允许的,这是有道理的。所以我尝试了以下内容:
const void* funcPtr = m_functions[i];
const T call = reinterpret_cast<const T>(funcPtr);
call(title, cause, file, line);
但这也不起作用。
这有效:
void* funcPtr = const_cast<void*>(m_functions[i]);
T call = reinterpret_cast<T>(funcPtr);
call(title,cause,file,line);
但我想避免使用const转换。我究竟做错了什么?我该如何调用这个const函数?或者它是不允许的,因为它不知道被调用的函数是否是const函数?或许这是因为我的静态函数不是类的成员所以它不能被声明为const?
答案 0 :(得分:2)
您将函数指针存储为const void*
:
const void* m_functions[kNbrMax];
您尝试将其投放到T
并使用reinterpret_cast
调用它:
reinterpret_cast<T>(m_functions[i])(title,cause,file,line);
但是,reinterpret_cast
无法从某个类型中删除const
限定符,因此,您应首先使用const
删除const_cast
:
reinterpret_cast<T>(const_cast<void*>(m_functions[i]))(title,cause,file,line);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
但是,请注意const_cast
会导致未定义的行为并且不安全。因此,如果原始指针实际上不是reinterpret_cast
,则调用从T
返回的函数指针。
修改
您可以调用const
限定函数指针,然后reinterpret_cast
应包含const
限定符:
reinterpret_cast<const T>(m_functions[i])(title,cause,file,line);