首页 > 解决方案 > 如何定义类类型转换为函数指针?

问题描述

我试图了解更多的类类型转换。我正在阅读 C++ 入门 5ed。所以我试过这段代码:

int add(int x, int y) { return x + y;}

struct Foo
{
    //operator(int(*)(int, int))(){return add;} // error
    using pfn = int(*)(int, int);
    operator pfn(){return add;} // OK
    double value = 5.45;
};

int main()
{

    cout << (int(*)(int, int))Foo()(5, 7) << endl; // why 1
    cout << ((int(*)(int, int))Foo())(5, 7) << endl; // Ok 12

    std::cout << "\nDone!\n";
}

标签: c++type-conversion

解决方案


  • 那么为什么我不能使用类型直接为我的类定义转换,int(*)(int, int)但我可以使用类型别名呢?

转换函数的“ TYPE”名称的语法operator比更通用的声明符或type-id更受限制。它根本不允许使用括号,只允许使用类型说明符(如类型别名、unsigned int、类名等)、*&&&const标记volatile的组合以及[[属性]]。我不能确切地说出为什么,但是像这样的复杂声明很难编写、阅读和解析。如果允许更多,在某些情况下可能存在潜在的歧义,或者他们只是不想要求编译器必须弄清楚这一点。

另外,如果允许话,表格可能是operator int (*())(int, int);而不是operator (int(*)(int, int))()?或者也许这也没有意义。看?棘手。

  • 为什么我在第一个错误的语句中得到值1,并在第二个语句中使用括号得到正确的值?

函数调用语法的优先级高于 C 风格的强制转换。所以

(int(*)(int, int))Foo()(5, 7)    // (1)
(int(*)(int, int)) (Foo()(5, 7)) // (2), same as (1)
((int(*)(int, int))Foo()) (5, 7) // (3), not the same

表达式 (1) 或 (2) 通过首先创建一个临时值来评估Foo。它后面是函数调用语法,并且Foo没有定义operator(),但是 C++ 还会检查它是否隐式转换为指针或对函数的引用并且确实如此,所以(5, 7)隐式转换并将结果指针调用到add,给出 12。这被转换为函数指针类型,该类型具有实现定义的结果。没有operator<<声明 for 函数指针,但有一个 for bool,并且函数指针可以隐式转换为bool。大概奇怪的转换的结果不是空指针值,所以最终结果是true,你会看到 value 1。(如果你之前做过std::cout << std::boolalpha,你应该看到true或适当的翻译。)

除了对运算符优先级的误解之外,其中一个原因是 C 风格转换的危险,它可以做很多不同的事情,有些事情通常不是有意的。改用static_cast<int(*)(int,int)>(Foo())(5,7),一切都很好。或者,如果我们不小心键入static_cast<int(*)(int,int)>(Foo()(5,7))了,编译器会给出一个关于从intto转换的错误int(*)(int,int),因为只有reinterpret_cast或 C 风格的转换可能会这样做。

  • 我从第一条语句中得到警告:Description Resource Path Location Type cast to pointer from integer of different size [-Wint-to-pointer-cast] main.cpp /MyCppProj line 31 C/C++ Problem

即使 C 风格的强制转换强制 fromint到函数指针的转换是有效的,编译器也会警告int没有足够的字节来表示函数指针。假设int之前的值来自将函数指针转换为某个数字类型,这意味着要转换回来,但是每当它从足够大的类型转换为 时int,指针值就会丢失。


推荐阅读