iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >如何使用C++获取指定的重载函数地址
  • 213
分享到

如何使用C++获取指定的重载函数地址

2024-04-02 19:04:59 213人浏览 泡泡鱼
摘要

刚刚看到一篇博客,说 std::bind 无法绑定正确的重载函数。这里的问题并不是 std::bind 能力不足,而是将函数名传递给 std::bind 时编译器无法取到这个函数的地

刚刚看到一篇博客,说 std::bind 无法绑定正确的重载函数。这里的问题并不是 std::bind 能力不足,而是将函数名传递给 std::bind 时编译器无法取到这个函数的地址(也就是符号,编译器会先解析成符号,链接器再替换为地址),因为有多个重载函数都是这个名字。核心问题是无法通过函数名取到想要的重载函数地址。就像下面的代码无法编译通过:

#include <iOStream>
void f()
{
    std::cout << "f 1" << std::endl;
}

void f(int x)
{
    std::cout << "f 2 " << x << std::endl;
}

int main()
{
    auto p = &f;
}

编译错误:

/home/abc/cpplearn/overload_func.cpp: In function ‘int main()’:
/home/abc/cpplearn/overload_func.cpp:15:15: error: unable to deduce ‘auto’ from ‘& f’
   15 |     auto p = &f;
      |               ^
/home/abc/cpplearn/overload_func.cpp:15:15: note:   couldn’t deduce template parameter ‘auto’

有没有什么比较完美的解决办法呢?我觉得一定有,因为 C 语言没有函数重载,函数地址作为实参也是常规操作。相比之下,c++ 引入了函数重载,却无法取到函数地址,这就很尴尬。C++ 设计者肯定也想到了这个问题。

于是查阅了 cppreference.com,看到了 Address of an overloaded function。函数名的重载解析除了发生在函数调用的时候,也会发生在以下 7 种语境:

#ContextTarget
1initializer in a declaration of an object or referencethe object or reference being initialized
2on the right-hand-side of an assignment expressionthe left-hand side of the assignment
3as a function call argumentthe function parameter
4as a user-defined operator argumentthe operator parameter
5the return statementthe return type of a function
6explicit cast or static_cast argumentthe target type of a cast
7non-type template argumentthe type of the template parameter

当函数名存在于这 7 种语境时,会发生重载解析,并且会选择与 Target 类型匹配的那个重载函数。这里就不一一考察这 7 种语境了,有兴趣可以自己查阅 cppreference.com。这里重点考察第 3 种和第 6 种。

先看第 3 种语境。当函数名作为函数调用的实参时,重载解析会选择和形参类型相匹配的版本。也就是说,下面的代码会如期运行:

#include <iostream>
void f()
{
    std::cout << "f 1" << std::endl;
}

void f(int x)
{
    std::cout << "f 2 " << x << std::endl;
}

void call(void p(int)) {
    p(1);
}

int main()
{
    call(f);
}

这段代码输出:

f 2 1

回到最初的问题,std::bind 也是函数,为什么无法正常编译呢?直接分析下面代码的编译错误信息:

#include <iostream>
#include <functional>

void f()
{
    std::cout << "f 1" << std::endl;
}

void f(int x)
{
    std::cout << "f 2 " << x << std::endl;
}

int main()
{
    auto new_func = std::bind(f, std::placeholders::_1);
    new_func(66);
}

编译错误:

/home/abc/cpplearn/overload_func.cpp: In function ‘int main()’:
/home/abc/cpplearn/overload_func.cpp:16:30: error: no matching function for call to ‘bind(<unresolved overloaded function type>, const std::_Placeholder<1>&)’
   16 |     auto new_func = std::bind(f, std::placeholders::_1);
      |                     ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~

可以看到,std::bind 准确地说是一个函数模板。它要根据其参数进行模板实参推导,再替换模板形参进行实例化(Instantiation),产生和普通函数类似的汇编代码。std::bind 进行实例化的时候,函数 f 还没有进行重载解析,其类型为<unresolved overloaded function type>。std::bind 无法进行实例化。怎样修改可以解决这个问题呢?

可以利用第 6 个语境,也就是显示转换或 static_cast。重载解析会选择与它们的目标类型相匹配的版本。下面的代码会如期运行:

#include <iostream>
#include <functional>

void f()
{
    std::cout << "f 1" << std::endl;
}

void f(int x)
{
    std::cout << "f 2 " << x << std::endl;
}

int main()
{
    auto new_func = std::bind((void(*)(int))f, std::placeholders::_1);
    new_func(66);
}

这段代码输出:

f 2 66

还有一种更加巧妙的办法,依然是利用第 3 种语境。既然 std::bind 的第一个模板实参的推导,和 f 的重载解析相矛盾。为什么不直接解决这个矛盾,将第一个模板实参改为显示指定?来看下面的代码:

#include <iostream>
#include <functional>

void f()
{
    std::cout << "f 1" << std::endl;
}

void f(int x)
{
    std::cout << "f 2 " << x << std::endl;
}

int main()
{
    auto new_func = std::bind<void(int)>(f, std::placeholders::_1);
    new_func(66);
}

这段代码如期输出:

f 2 66

总结

到此这篇关于如何使用C++获取指定的重载函数地址的文章就介绍到这了,更多相关C++获取重载函数地址内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 如何使用C++获取指定的重载函数地址

本文链接: https://www.lsjlt.com/news/150962.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何使用C++获取指定的重载函数地址
    刚刚看到一篇博客,说 std::bind 无法绑定正确的重载函数。这里的问题并不是 std::bind 能力不足,而是将函数名传递给 std::bind 时编译器无法取到这个函数的地...
    99+
    2024-04-02
  • 使用Java如何获取IP地址
    本篇文章给大家分享的是有关使用Java如何获取IP地址,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。一、通过IP获取机器名 or 通过机器名获取iphost :主机 ...
    99+
    2023-05-31
    java ip ava
  • C++函数重载怎么定义使用
    这篇文章主要介绍了C++函数重载怎么定义使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C++函数重载怎么定义使用文章都会有所收获,下面我们一起来看看吧。一、函数重载分析(上)1.1 重载的定义定义:同一个标...
    99+
    2023-06-30
  • vue如何获取地址栏的参数
    具体方法如下:使用params方式获取地址栏参数export default new Router({routes: [{ path: '/', name: 'LoginView', component: L...
    99+
    2024-04-02
  • 如何使用 C++ 函数指针重载和泛型编程?
    c++++ 函数指针重载通过指定不同函数签名实现指向具有相同名称但不同参数或返回值的多函数指针。泛型编程使用模板创建适用于不同类型数据的函数和数据结构,使代码可重用。使用函数指针重载需要...
    99+
    2024-04-17
    c++ 函数指针 泛型编程
  • 如何使用 Golang 获取我的 wifi IP 地址?
    php小编小新在这里为大家介绍如何使用Golang获取自己的wifi IP地址。Golang是一种高效且简洁的编程语言,它提供了很多方便的方法来处理网络相关的任务。要获取wifi IP...
    99+
    2024-02-09
  • C++ 函数重载如何与虚函数结合使用?
    函数重载和虚函数可以结合使用,允许子类在不修改父类行为的情况下,以不同方式实现相同操作的不同方面。通过在父类中声明虚函数,并在子类中重载它们,我们可以实现动态多态,允许通过父类引用调用不...
    99+
    2024-04-13
    c++ 函数重载 虚函数
  • python如何使用sample()函数从指定序列中随机获取指定长度的片段
    这篇文章给大家分享的是有关python如何使用sample()函数从指定序列中随机获取指定长度的片段的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。sample(sequence,k)从指定序列中随机获取指定长度的...
    99+
    2023-06-08
  • C++ 函数重载中的 best match 是如何决定的?
    最佳匹配的确定顺序是:精度匹配标准转换用户定义转换默认参数数量最少 C++ 函数重载中的最佳匹配是如何决定的? 在 C++ 中,函数重载允许您创建具有相同名称但参数不同的多个函数版本。...
    99+
    2024-04-26
    函数重载 c++ 隐式转换
  • 如何在 C++ 中有效使用函数重载和重写
    函数重载与重写指南:函数重载: 创建多个具有相同名称但不同参数的函数,减少代码冗余。函数重写: 子类中声明同名函数,修改继承函数的行为,实现多态。实战案例:函数重载:处理不同数据类型。函...
    99+
    2024-04-20
    函数重载 函数重写 c++ 代码可读性
  • torch.hub.load()函数的使用——联网加载权重以及如何加载本地权重
    torch.hub.load()函数可以通过两种方式加载模型。 pytorch官方文档 函数原型: torch.hub.load(repo_or_dir, model, *args, source='...
    99+
    2023-08-31
    pytorch 深度学习 python
  • C++ 函数重载如何用于函数模板化?
    函数重载与模板化应用:函数重载:允许在同一作用域内定义同名函数,但参数类型不同。函数模板化:创建通用函数,可操作不同类型的数据。结合使用:利用函数重载的灵活性创建针对不同类型参数的通用函...
    99+
    2024-04-13
    c++ 函数重载 函数模板化 作用域
  • C++ 函数重载中参数的顺序如何影响重载?
    在 c++++ 函数重载中,参数顺序至关重要,编译器根据参数顺序区分重载函数,即使参数类型相同,顺序不同的函数也会被视为不同的函数。 C++ 函数重载中的参数顺序 函数重载允许创建具有...
    99+
    2024-04-28
    c++ 函数重载
  • python中如何使用get获取指定键值
    小编给大家分享一下python中如何使用get获取指定键值,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!1、说明在使用字典时,很少直接输出它的内容。一般需要根据指定的键得到相应的结果。Python 中推荐的方法是使用字典对...
    99+
    2023-06-15
  • C++ 函数重载和重写的理解和使用
    c++++ 中函数重载允许在同一类中定义同名函数,但参数列表不同;函数重写发生在子类中定义一个与父类同名且参数相同的函数,子类函数将覆盖父类函数。实战示例中,重载函数用于针对不同数据类型...
    99+
    2024-04-20
    函数重载 函数重写 c++
  • 用户的MAC地址如何利用java实现获取
    用户的MAC地址如何利用java实现获取?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。java实现获取用户的MAC地址方法:方法一:将本机地址与局域网内其他机器区分开来 p...
    99+
    2023-05-31
    java mac地址 ava
  • C++ 函数重载和重写中引用和指针的处理
    函数重载时,传递引用或指针,所有函数必须使用相同类型的数据。函数重写时,对于引用成员函数,子类函数必须引用同一类型变量;对于指向成员函数,子类函数必须指向同一类型变量。 C++ 函数重...
    99+
    2024-04-20
    函数重载 引用指针处理 c++ 作用域
  • Python中如何使用专用网站获取本机IP地址
    这篇文章给大家分享的是有关Python中如何使用专用网站获取本机IP地址的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。使用专用网站获取的是公网IP网址:http://myip.i...
    99+
    2024-04-02
  • C++ 函数重载何时应该避免使用?
    避免使用 c++++ 函数重载的情况:参数太多(3-4 个以上)参数类型相似(可能导致混淆)性能开销(编译时间和运行时开销)限制代码可读性(难以跟踪不同参数组合) C++ 函数重载:何...
    99+
    2024-04-28
    c++ 函数重载 代码可读性
  • C++ 函数重载中参数的数据类型如何影响重载?
    函数重载中参数的数据类型影响解析,匹配过程基于类型。数据类型提升和转换可能改变匹配。void 类型可与任何参数类型匹配。实践中,根据参数类型调用合适的重载函数,实现类型特定的处理。 C...
    99+
    2024-04-27
    c++ 函数重载
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作