c++ - C++ 中函数签名的定义顺序

标签 c++ c++11 type-conversion

我有一个函数指针表,我正在尝试确定定义函数签名的顺序是否重要。看看我下面的例子,我想知道为什么 Method 1 不能编译,即使它的函数指针类型可以通过 decltype 确定。我想知道如何才能使 Method 1 工作。有任何想法吗?谢谢。

// Method 1
typedef struct FOO_FUNCS
{
    void( WINAPI * pfnFoo) ();
} FOO_FUNCS;
typedef decltype(&FOO_FUNCS::pfnFoo) PFN_FOO;

// Method 2
typedef void (WINAPI* PFN_BAR)();
typedef struct BAR_FUNCS
{
    PFN_BAR pfnBar;
} BAR_FUNCS;

class FooBarClass
{
public:
    static void WINAPI Foo()
    {
        cout << "Foo" << "\n";
    }
    static void WINAPI Bar()
    {
        cout << "Bar" << "\n";
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    void* pfnFoo = reinterpret_cast<void*>(FooBarClass::Foo);
    reinterpret_cast<PFN_FOO>(pfnFoo) (); <= = this gives me "error C2440 : 'reinterpret_cast' : cannot convert from 'void *' to 'PFN_FOO'"

    void* pfnBar = reinterpret_cast<void*>(FooBarClass::Bar);
    reinterpret_cast<PFN_BAR>(pfnBar) ();
}

最佳答案

展开typedefs和decltype后,PFN_FOOFOO_FUNCS成员指针 ,成员的类型是指向 void WINAPI () 的指针.您不能在指向成员的指针和 void* 之间进行转换.这就是您收到错误的原因。


我不确定,但我相信您可能一直在寻找其中之一:

typedef decltype(FOO_FUNCS().pfnFoo) PFN_FOO;

typedef decltype(&FOO_FUNCS().pfnFoo) PFN_FOO;

(在一般情况下,您更愿意使用 std::declval<FOO_FUNCS>() 而不是上面的 FOO_FUNCS(),因为它不需要可访问的默认构造函数)。

或者也许是最简单的(感谢@Jarod42):

typedef decltype(FOO_FUNS::pfnFoo) PFN_FOO;

下面是每个 typedef 更详细的作用:

decltype(FOO_FUNCS().pfnFoo)

表达式是FOO_FUNCS().pfnFoo .即创建一个默认构造的FOO_FUNCS对象并访问其数据成员 pfnFoo . decltype()应用于这样的表达式会产生数据成员的类型,即 void( WINAPI * ) () .这是一个指向 WINAPI 的指针函数不带参数并返回 void .

decltype(&FOO_FUNCS().pfnFoo)

表达式是&FOO_FUNCS().pfnFoo .即创建一个默认构造的FOO_FUNCS对象,访问其数据成员 pfnFoo并获取它的地址(在内存中)。 this 的类型是“指向 pfnFoo 类型的指针;”这意味着这个 decltype 等同于 decltype(FOO_FUNCS().pfnFoo) * .所以它是void( WINAPI * * ) () - 指向 WINAPI 的指针函数不带参数并返回 void .

decltype(FOO_FUNCS::pfnFoo)

表达式是FOO_FUNCS::pfnFoo .即,将数据成员命名为pfnFooFOO_FUNCS . decltype()产生该数据成员的类型,又是 void( WINAPI * ) () - 指向 WINAPI 的指针函数不带参数并返回 void .

还有你原来的:

decltype(&FOO_FUNCS::pfnFoo)

表达式是&FOO_FUNCS::pfnFoo .也就是说,取指向成员的指针(有时不准确地称为“成员指针”)pfnFooFOO_FUNCS .类型是 void (WINAPI (FOO_FUNCS::*)*) () - 指向类成员的指针 FOO_FUNCS ,其中成员具有指向 WINAPI 的类型指针函数不带参数并返回 void .

最后一个是根本不同的 - 另一个只是尝试以不同的方式访问成员作为变量(通过临时,通过限定名称),如果你愿意的话,这是一 block 物理内存。最后一个将其视为“逻辑”成员,作为类中的“偏移量”。这与指针 ( T* ) 和指向类 X 成员的指针之间的根本区别相同。 (T X::*)。

关于c++ - C++ 中函数签名的定义顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23866377/

相关文章:

使用 lambda 的 C++ 回调因 bad_function_call 而失败

python - 使用以下系列计算 π 的值(Matlab 转换)

c++ - 从映射值中的 unique_ptr 迭代原始指针

c++ - 调度 SIMD 指令 + SIMDPP + qmake

c++ - Vim,帮助 YCM 为 c++ 工作

c++ - 在 C++ 代码生成器中模仿 C# 'new'(隐藏虚方法)

c++ - 在不同线程中调用 std::function

c++ - 使用智能指针

从 const int* 到 int* 的 C++ 转换处理意外结果

polymorphism - SML中不使用数据类型的多态加法函数