了解编译器如何解析指向函数的指针

时间:2014-11-07 01:08:04

标签: c++ function function-pointers

以下代码段:

#include <iostream>

void does() { std::cout << "do" << std::endl; }
void does(bool b = false) { std::cout << "do(bool)" << std::endl; }

void fwd(void (*func)(bool))
{
    func(false);
}

int main(int, char**)
{
    fwd(&does);
    fwd(does);
    fwd(*does);
}

可以理解地产生以下错误:

test.cpp:15:10: error: overloaded function with no contextual type information

编译器无法识别我打算使用哪些函数。 我不明白为什么当我注释掉以下行:

时,代码将正确运行

fwd(*does)

为什么编译器会突然解决模糊性问题?

int main(int, char**)
{
    fwd(&does);
    fwd(does);
}

此外,在不重载does的情况下,代码段将正确运行所有3个调用。 这个片段运行良好......

#include <iostream>

void does(bool b = false) { std::cout << "do(bool)" << std::endl; }

void fwd(void (*func)(bool))
{
    func(false);
}

int main(int, char**)
{
    fwd(&does);
    fwd(does);
    fwd(*does);
}

我正在Linux机器上用gcc 4.6.3编译它。

感谢您的帮助!

2 个答案:

答案 0 :(得分:7)

您的问题的答案在于函数的重载决策规则 具体来说,在函数名称(一次)没有破坏过载分辨率之前使用&会有例外,但是使用*时没有异常。 另请注意,这两个函数中只有一个接受该单个参数:

  

13.4重载函数[over.over]

的地址      

1使用不带参数的重载函数名在某些上下文中解析为函数,指向函数的指针或指向过载集中特定函数的成员函数的指针。函数模板名称被认为是在这种上下文中命名一组重载函数。 选择的函数是其类型与上下文中所需的目标类型的函数类型相同的函数。 [注意:即,忽略函数所属的类匹配指向成员函数类型的指针时。 -end note] 目标可以是

     
      
  • 正在初始化的对象或引用(8.5,8.5.3),
  •   
  • 作业的左侧(5.17),
  •   
  • 函数的参数(5.2.2),
  •   
  • 用户定义的运算符的参数(13.5),
  •   
  • 函数,运算符函数或转换的返回值(6.6.3),
  •   
  • 显式类型转换(5.2.3,5.2.9,5.4)或
  •   
  • 非类型模板参数(14.3.2)。
  •   
     

重载的函数名称可以以&运算符开头。如果没有参数,则不应在没有列出的上下文中使用重载的函数名。

引用来自n3242(c ++ 11),由我加粗。

答案 1 :(得分:0)

fwd期望一个带有布尔参数的函数;你只有一个does这样的版本,所以没有混淆。实际上,does&does被认为是相同的(因为函数不能是值,这两个中的一个在技术上应该是不正确的,如果不是无法表示,但语言必须选择只是对待它们同样的事情)。

但是当你尝试使用fwd(*does)时,你需要does定义解除引用到这样一个函数,而你没有这样的东西 - - 事实上,正如我最近接受过教育,你不能有类似的东西。