Да, вы в безопасности.То, что вы делаете, охватывается случаем «За исключением этого преобразования ...».
Причина, по которой он вызывается, состоит в том, чтобы позволить вам передавать указатели на функции через указатель на функцию другого типа.Таким образом, вы можете определить что-то вроде:
enum CallbackType {
eFuncPtrVoidReturningVoid,
eFuncPtrVoidReturningInt,
// ... more as needed ...
};
class CallbackRecord
{
public:
CallbackRecord(void (*cb)()): cbType(eFuncPtrVoidReturningVoid), cbFunc(cb)
{}
CallbackRecord(int (*cb)()): cbType(eFuncPtrVoidReturningInt),
cbFunc(reinterpret_cast<void (*)()>(cb)) {}
void operator()() const;
protected:
CallbackType cbType;
void (*cbFunc)();
};
void CallbackRecord::operator()() const
{
switch(cbType)
{
case eFuncPtrVoidReturningVoid:
(*cbFunc)();
break;
case eFuncPtrVoidReturningInt:
while((*reinterpret_cast<int (*)()>(cbFunc))())
;
break;
}
}
. Хотя вы можете просто сказать «сделать все обратные вызовы возвращаемыми int
», для этого потребуется написать оболочки для всего, что не соответствует соглашению о вызовах, если числоиз типов обратного вызова выходит за рамки двух.Разрешение этих типов указателей на функции дает вам альтернативное средство поддержки нескольких типов обратного вызова и избавляет нас от необходимости превращать CallbackRecord
в шаблон.Это также позволяет использовать подклассы или маршалинг для замены вышеприведенного оператора switch
, не требуя использования методов virtual
.