【问题标题】:What does a function name indicate and more函数名称表示什么等等
【发布时间】:2018-10-19 13:15:53
【问题描述】:

考虑这个简单的程序:

#include <iostream>

void length(void){
    std::cout<<"My length is void"<<std::endl;
}

void width(void){
    std::cout<<"My width is void"<<std::endl;
}

int main(void){
    std::cout<<"The program length is: "<<length<<std::endl;
    std::cout<<"The program width is: "<<width<<std::endl;
}

这个程序的输出是:

The program length is: 1
The program width is: 1

程序打印出来的数字是什么,基本上没有太多的C++知识,这对我来说看起来更像pythonic语法,看起来好像应该打印函数地址。我这么说是因为,这个问题最初是在练习一些非常基本的openGL程序时出现的,

回调在 GLUT 中注册,如下所示:

void line(void){
   //some code for line program ...
}

int main(int argc, char** argv){
    //some more code;
    glutDisplayFunc(line);
    glutMainLoop();
}    

看起来好像我们在传递函数的地址,但是,从上面的程序很明显这不是地址,并且指向函数的语法有点不同,如果是这样,如何这个函数是否注册回调?我们要传递给glutDisplayFunc的是什么?

而且,由于我**想注册一个已传递参数的函数,所以我在 C++ 类比中搜索了 python lambda 函数,并找到了类似的 lambda 函数,但没有成功:**

#include <iostream>

void line(int a,  int b){
//some code that does some plotting  in  the  display window
}

int main(int argc, char** argv){

     auto callback = [](void)->void{
             line(a,b);
           };

     glutDisplayFunc(callback);
     glutMainLoop();
}

这完全失败了,显示的错误是:

no suitable conversion function from "lambda []void ()->void" to "void (*)()" exists   

这是使用我的 python 类比,但是这个问题的解决方案是什么?混淆的主要部分以粗体突出显示。

【问题讨论】:

  • 在 C++ 中,非成员函数自然会衰减为指向自身的指针。在这种情况下,line 等于 &amp;line
  • 您问题的前半部分已回答here。我建议从你的问题中删除它,然后问为什么你不能通过 lambda。
  • Lambda 具有编译器生成的类型,这些类型不同于所有其他类型 - 特别是与(指向)函数的不同类型。您的函数需要一个指向不接受参数并返回void(即void (*)())的函数的指针。没有 lambda 可以有这种类型。
  • @Peter 但是,非捕获 lambdas 将隐式转换运算符获取到其调用类型的函数指针。 [](){} 可以隐式转换为 void(*)()

标签: c++ opengl glut


【解决方案1】:

看起来好像我们在传递函数的地址,但是,从上面的程序中可以明显看出这不是地址

你把事情搞反了。不是glutDisplayFunc 在做奇怪的魔法事情;这是std::cout

是的,函数名将转换为函数指针。 iostream 的 operator&lt;&lt; 重载和 C++ 重载解析规则的组合最终导致 &lt;&lt; 将函数视为 布尔值(是的,真的)。因此,您的&lt;&lt; length 等同于&lt;&lt; true

如果你想要地址,你可以在输出之前将函数指针转换为void*&lt;&lt; reinterpret_cast&lt;void*&gt;(&amp;length) 或更简洁的&lt;&lt; (void*)&amp;length(虽然从技术上讲,这只是 C++ 有条件地支持,几乎每个真正的编译器将允许这样做)。

最后,在 C++ 中,lambda 不是函数。它们是对象。您不能将对象传递给需要函数指针的对象。您可以将无捕获的 lambda 转换为函数指针,但不能对捕获值的 lambda 执行此操作。

【讨论】:

  • 如果你使用std::boolalpha 操纵器,std::cout &lt;&lt; length 打印true
  • 可以添加一个简短的注释,说明当您将所述指针投射到 void* 以绕过/跳过/傻瓜/触发转换为布尔时会发生什么
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-23
  • 2023-03-20
  • 2011-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多