C/C++中重载函数取地址的方法

目录

1.现象

2.指定参数取函数地址

3.利用Qt的类QOverload


1.现象

        函数重载在C/C++编码中是非常常见的,但是我们在std::bind或std::function绑定函数地址的时候,直接取地址,程序编译就会报错,示例如下:

class CFunc12345
{
public:void func12345(int x) {std::cout << x;}void func12345(double x) {std::cout << x;}
};void func67890(int x) {std::cout << x;
}
void func67890(double x) {std::cout << x;
}int main()
{CFunc12345 x1;auto p = std::bind(&CFunc12345::func12345, x1, std::placeholders::_1); //[1]编译报错p(14124);auto p1 = std::bind(&func67890, std::placeholders::_1);  //[2]编译报错p1(33333333);std::function<void(int)> p2(&func67890);  //[3]编译报错p2(33333333);return 0;
}

上述代码[1],[2],[3]处都会出现编译错误,那是因为函数重载,多个函数名相同,找不到该用那个函数地址。这个时候解决办法就是人为指定用那个函数,那么人为指定用那个函数有哪些办法呢?

2.指定参数取函数地址

方法如下:

    //方法1:CFunc12345 x1;using FUNC1 = void (CFunc12345::*)(int);FUNC1 func1 = &CFunc12345::func12345;auto p1 = std::bind(func1, x1, std::placeholders::_1);p1(14124);using FUNC2 = void(*)(int);FUNC2 func2 = &func67890;auto p2 = std::bind(func2, std::placeholders::_1);p2(14124);FUNC2 func3 = &func67890;std::function<void(int)> p3(func3);p3(14124);

从代码可以看出,就是手动指定函数类型,先取到函数地址后,再把地址传入指定的对象(如std::bind、std::function等)中,避免了std::bind或std::function去判断函数类型,从而避免了编译错误。

3.利用Qt的类QOverload

        QOverload是Qt5中提供的一种用于重载信号和槽函数连接的方式。它允许开发者在使用信号与槽机制时,更灵活地处理函数重载的情况。通过将信号和槽函数的参数类型转换为指定类型,QOverload实现了对信号和槽函数的类型安全检查。

        在实际应用中,QOverload通过重载调用QOverload::of,利用它来指定多个信号版本中的具体哪种类型参数。例如,当有一个信号函数被重载,具有多个不同参数类型的版本时,可以使用QOverload来明确指定要连接的是哪个版本的信号函数。

        QOverload的作用就是指定重载函数中的函数类型,从它的源码中可以看出来,源码如下:

template <typename... Args>
struct QNonConstOverload
{template <typename R, typename T>Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...)) const Q_DECL_NOTHROW -> decltype(ptr){ return ptr; }template <typename R, typename T>static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...)) Q_DECL_NOTHROW -> decltype(ptr){ return ptr; }
};template <typename... Args>
struct QConstOverload
{template <typename R, typename T>Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...) const) const Q_DECL_NOTHROW -> decltype(ptr){ return ptr; }template <typename R, typename T>static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...) const) Q_DECL_NOTHROW -> decltype(ptr){ return ptr; }
};template <typename... Args>
struct QOverload : QConstOverload<Args...>, QNonConstOverload<Args...>
{using QConstOverload<Args...>::of;using QConstOverload<Args...>::operator();using QNonConstOverload<Args...>::of;using QNonConstOverload<Args...>::operator();template <typename R>Q_DECL_CONSTEXPR auto operator()(R (*ptr)(Args...)) const Q_DECL_NOTHROW -> decltype(ptr){ return ptr; }template <typename R>static Q_DECL_CONSTEXPR auto of(R (*ptr)(Args...)) Q_DECL_NOTHROW -> decltype(ptr){ return ptr; }
};

顾名思义,模版类QNonConstOverload是取不带const的类成员函数的地址的,模版类QConstOverload是取带const的类成员函数的地址的,QOverload是取普通函数地址的,它们之间的关系如下图所示:

于是上面编译错误的代码可以修改为:

int main()
{//方法2CFunc12345 x1;auto p = std::bind(QOverload<int>::of(&CFunc12345::func12345), x1, std::placeholders::_1);p(14124);auto p1 = std::bind(QOverload<int>::of(&func67890), std::placeholders::_1);p1(33333333);std::function<void(int)> p2(QOverload<int>::of(&func67890));p2(33333333);return 0;
}

QOverload看似只有装有Qt环境才能用,其实把源码稍加修改就可以作为标准的C++类来用,修改后的COverload源码如下所示:

template <typename... Args>
struct CNonConstOverload
{template <typename R, typename T>auto operator()(R(T::* ptr)(Args...)) const -> decltype(ptr){return ptr;}template <typename R, typename T>static auto of(R(T::* ptr)(Args...)) -> decltype(ptr){return ptr;}
};template <typename... Args>
struct CConstOverload
{template <typename R, typename T>auto operator()(R(T::* ptr)(Args...) const) const -> decltype(ptr){return ptr;}template <typename R, typename T>static auto of(R(T::* ptr)(Args...) const) -> decltype(ptr){return ptr;}
};template <typename... Args>
struct COverload : CConstOverload<Args...>, CNonConstOverload<Args...>
{using CConstOverload<Args...>::of;using CConstOverload<Args...>::operator();using CNonConstOverload<Args...>::of;using CNonConstOverload<Args...>::operator();template <typename R>auto operator()(R(*ptr)(Args...)) const -> decltype(ptr){return ptr;}template <typename R>static auto of(R(*ptr)(Args...)) -> decltype(ptr){return ptr;}
};

QOverload在Qt的信号槽中也用的比较多。信号槽连接时,使用基于字符串的语法,可以显式指定参数类型。因此,使用重载信号或槽的哪一个实例是明确的。相反,使用基于模版函数的语法,必须强制转换重载信号或槽,以告诉编译器要使用哪个实例。

        例如,QLCDNumber有三个版本的display() 槽函数:

        1.QLCDNumber::display(int)

        2.QLCDNumber::display(double)

        3.QLCDNumber::display(QString)

使用信号QSlider::valueChanged()和QLCDNumber::display(int)连接,可以有如下系列方法:

     auto slider = new QSlider(this);auto lcd = new QLCDNumber(this);// String-based syntaxconnect(slider, SIGNAL(valueChanged(int)),lcd, SLOT(display(int)));// Functor-based syntax, first alternativeconnect(slider, &QSlider::valueChanged,lcd, static_cast<void (QLCDNumber::*)(int)>(&QLCDNumber::display));// Functor-based syntax, second alternativevoid (QLCDNumber::*mySlot)(int) = &QLCDNumber::display;connect(slider, &QSlider::valueChanged,lcd, mySlot);// Functor-based syntax, third alternativeconnect(slider, &QSlider::valueChanged,lcd, QOverload<int>::of(&QLCDNumber::display));// Functor-based syntax, fourth alternative (requires C++14)connect(slider, &QSlider::valueChanged,lcd, qOverload<int>(&QLCDNumber::display));

        总的来说,QOverload是一个强大的工具,它使得在Qt中使用信号和槽机制时,处理函数重载的情况变得更加简单和直观。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/779298.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++】map set

文章目录 1. 关联式容器2. 键值对3. 树形结构的关联式容器3.1 set3.1.1 set 的介绍3.1.2 set 的使用 3.2 map3.2.1 map 的介绍3.2.2 map 的使用 3.3 multiset3.3.1 multuset 的介绍3.3.2 multiset 的使用 3.4 multimap3.4.1 multimap 的介绍3.4.2 multimap 的使用 1. 关联式容器…

Docker安装xxl-job并整合到SpringBoot项目

1. 创建数据库 执行如下SQL语句创建相关表 CREATE database if NOT EXISTS xxl_job default character set utf8mb4 collate utf8mb4_general_ci; use xxl_job;SET NAMES utf8mb4; CREATE TABLE xxl_job_info (id int(11) NOT NULL AUTO_INCREMENT,job_group int(11) NOT NUL…

深入Python元编程:从基础到实践

一、引言 Python的元编程是一种强大的技术&#xff0c;允许程序员在运行时修改或扩展程序的行为。通过元编程&#xff0c;你可以控制类的创建、修改类的行为、操作函数和类等对象&#xff0c;甚至创建新的语法结构。这篇文章将引导你走进Python元编程的世界&#xff0c;从基础…

PyCharm代码一键格式化

前言 每次写完代码&#xff0c;就看见很多警告&#xff0c;乍一看还以为我又写了什么bug&#xff0c;原来是提示&#xff0c;啊放心了。可是我可见不得这些东西&#xff0c;因为代码里都是红红的下划线&#xff0c;好像在圈圈点点。。。 代码格式化 于是利用PyCharm里的快捷…

数据仓库——维度表特性

企业信息化工厂 数据集市中的一致性&#xff0c;由于企业信息化工厂的数据集市是从集成仓库中获得信息的&#xff0c;因此至少从维度建模的角度来看&#xff0c;一致性维护的问题减少了。尽管合并不同数据源的问题依然在&#xff0c;但是负担主要在设计者身上。尽管压力降低了…

【Go】六、函数

文章目录 1、函数的定义2、内存分析3、注意点4、函数数据类型5、自定义数据类型&#xff08;起别名&#xff09;6、支持对返回值命名 1、函数的定义 语法&#xff1a; func 函数名&#xff08;形参列表)&#xff08;返回值类型列表&#xff09;{执行语句..return 返回值列…

mac系统使用经验

mac安装brew brew是macos下的一个包管理工具&#xff0c;类似与centos的yum&#xff0c;ubuntu的apt-get等。 自动脚本(全部国内地址)&#xff08;在Mac os终端中复制粘贴回车下面这句话) /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/H…

PHP实现单列内容快速查重与去重

应用场景:excel一列内容比如身份证号&#xff0c;可能有重复的&#xff0c; 则用此工具快速查询那些重复及显示去重后内容。 使用&#xff1a;粘贴一列数据&#xff0c;然后提交发送。 <?php $tm "单列查重去重(粘贴Excel中1列内容查重)!";function tipx($str…

无人驾驶矿卡整体解决方案(5g物联网通信方案)

​无人驾驶矿卡是智能矿山的重要组成部分,通过远程操控替代人工驾驶,可以显著提高采矿效率和作业安全性。但要实现无人驾驶矿卡,需要依赖于可靠高效的通信网络,来传输现场视频、控制指令和运行数据。以下是某大型煤矿在部署无人驾驶矿卡时,所采用的星创易联物联网整体解决方案。…

关于gson解析把int类型转成浮点型的问题

在进行开发的时候&#xff0c;通过gson进行数据解析的时候会把数值型转成浮点类型&#xff0c;造成数据处理错误的问题&#xff0c;网上关于解决这个问题的方法一大堆&#xff0c;但是 没有几个是能够解决这个问题的。 首先在获取到json数据时&#xff0c;你看到的是整数类型都…

基于springboot实现校园周边美食探索及分享平台系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现园周边美食探索及分享平台系统演示 摘要 美食一直是与人们日常生活息息相关的产业。传统的电话订餐或者到店消费已经不能适应市场发展的需求。随着网络的迅速崛起&#xff0c;互联网日益成为提供信息的最佳俱渠道和逐步走向传统的流通领域&#xff0c;传统的…

网络服务第三次作业

综合练习&#xff1a;请给openlab搭建web网站 网站需求&#xff1a; 1.基于域名www.openlab.com可以访问网站内容为 welcome to openlab!!! 2.给该公司创建三个子界面分别显示学生信息&#xff0c;教学资料 和缴费网站&#xff0c;基于&#xff0c;www.openlab.com/data网站访问…

Leetcode 1143:最长公共子序列

Leetcode原题 Leetcode 1143:最长公共子序列 题目标签 字符串 | 动态规划 题目描述 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 &#xff0c;返回 0 。一个字符串的 子序列 是指这样一个新的字符串&…

Unity 镜头动画

在Unity中&#xff0c;新建摄像机并用Animation组件去记录和控制视角&#xff0c;实现镜头动画的过程主要包括以下几个步骤&#xff1a; 新建摄像机 创建摄像机&#xff1a; 打开Unity项目&#xff0c;在Hierarchy视窗中右键点击&#xff0c;选择GameObject -> Camera来创…

暴力枚举--烤鸡

题目背景 猪猪 Hanke 得到了一只鸡。 题目描述 猪猪 Hanke 特别喜欢吃烤鸡&#xff08;本是同畜牲&#xff0c;相煎何太急&#xff01;&#xff09;Hanke 吃鸡很特别&#xff0c;为什么特别呢&#xff1f;因为他有 10 种配料&#xff08;芥末、孜然等&#xff09;&#xff0…

ruoyi使用笔记

1.限流处理 RateLimiter PostMapping("/createOrder") ApiOperation("创建充值订单") RateLimiter(key CacheConstants.REPEAT_SUBMIT_KEY,time 10,count 1,limitType LimitType.IP) public R createOrder(RequestBody Form form) {//业务处理return …

YOLOV8逐步分解(2)_DetectionTrainer类初始化过程

接上篇文章yolov8逐步分解(1)--默认参数&超参配置文件加载继续讲解。 1. 默认配置文件加载完成后&#xff0c;创建对象trainer时&#xff0c;需要从默认配置中获取类DetectionTrainer初始化所需的参数args&#xff0c;如下所示 def train(cfgDEFAULT_CFG, use_pythonFalse…

python的神奇bug2

今天测试出一个很诡异的bug&#xff0c; 这个错误还真的很难发现 测试1 a [1,10,100] for i in a:print(i)if(i10):a[20,30,-1]一般来说我们在进行迭代时&#xff0c;a这个值时不能改动的&#xff0c;但是现在的问题时如果我不小心给改动了呢&#xff0c;结果如下 也就是说…

基于JSPM的美食推荐管理系统

背景 互联网的迅猛扩张彻底转变了全球各类组织的运营模式。自20世纪90年代起&#xff0c;中国各级政府和企事业单位便开始探索运用网络系统来处理管理事务。然而&#xff0c;早期的网络覆盖不广、用户接受度不高、相关网络法规不健全以及技术发展不成熟等因素&#xff0c;都曾…

智慧商场数字化创新需要有数字能力帮手

商场和商圈是是促进流通创新、培育新兴消费的载体。很多实体店为适应消费升级需求新变化&#xff0c;加快运用现代信息技术&#xff0c;建设智慧商店&#xff0c;创新消费场景。蚓链运用现代信息技术&#xff08;互联网、物联网、5G、大数据、人工智能、云计算等&#xff09;&a…