将指向函数的指针转换为指向函数类型的不同指针的结果

时间:2011-12-11 15:07:00

标签: c++ function-pointers reinterpret-cast

  

(5.2.10 / 6)C ++ 03指向函数的指针可以显式转换为指向不同类型函数的指针。调用函数的效果   通过指向与...不同的函数类型(8.3.5)的指针   函数定义中使用的类型是未定义的。除了   将“指针指向T1”的rvalue转换为“指针”类型   至T2“(其中T1和T2是函数类型)并返回其原始状态   type产生原始指针值,这种指针的结果   转换未指定。 [注:有关详细信息,请参阅4.10   指针转换。]

以下是我正在尝试做的事情,虽然很明显将fp1转换为fp2的结果会产生原始指针,但同时标准中的措辞会{ {1}}这是什么意思?

"The result of such a pointer conversion is unspecified"

3 个答案:

答案 0 :(得分:5)

是的,这是安全的 reinterpret_cast只允许您将一个指针强制转换为另一个,但它不保证任何安全性,并且未指定使用此类指针的结果,除非它被强制转换回其原始类型。

提到的标准引用指定如果将一种类型的函数指针类型转换为另一种类型并尝试通过它调用函数,则结果是未定义的。

然而,
reinterpret_cast保证如果将类型转换指针强制转换回原始类型,那么指针就会很好地形成。

您的代码尝试执行第二次操作,因此它是安全的。

答案 1 :(得分:5)

您误读标准,“未指定”部分仅适用于其他转化:

  

除[特殊情况]外,未指定此类指针转换的结果。

那个[特例]是你转换回原始函数指针类型的那个,就像你的例子一样。在这种特殊情况下,转换产生原始指针值,因此可以像在您的示例中一样使用它。

仅针对其他转化,结果未指定。

答案 2 :(得分:4)

是的,你很安全。你正在做的事情被“转换......除外”案件所涵盖。

它被调用的原因是让你通过另一种类型的函数指针传递函数指针。所以你可以定义类似的东西:

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方法。