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()
{
    //方法2
	CFunc12345 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 syntax
     connect(slider, SIGNAL(valueChanged(int)),
             lcd, SLOT(display(int)));

     // Functor-based syntax, first alternative
     connect(slider, &QSlider::valueChanged,
             lcd, static_cast<void (QLCDNumber::*)(int)>(&QLCDNumber::display));

     // Functor-based syntax, second alternative
     void (QLCDNumber::*mySlot)(int) = &QLCDNumber::display;
     connect(slider, &QSlider::valueChanged,
             lcd, mySlot);

     // Functor-based syntax, third alternative
     connect(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.mfbz.cn/a/499611.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【全套源码教程】基于SpringBoot+MyBatis框架的智慧生活商城系统的设计与实现

目录 前言 需求分析 可行性分析 技术实现 后端框架&#xff1a;Spring Boot 持久层框架&#xff1a;MyBatis 前端框架&#xff1a;Vue.js 数据库&#xff1a;MySQL 功能介绍 前台功能拓展 商品详情单管理 个人中心 秒杀活动 推荐系统 评论与评分系统 后台功能拓…

慢工之旅:婺源的故事

在当今这个快节奏、高竞争的时代&#xff0c;我们常常发现自己处于持续的忙碌和压力之中。然而&#xff0c;在今年春季&#xff0c;我们选择了一条不同的道路——一次团队旅行到江西婺源。这不仅是一场远离日常工作的旅行&#xff0c;而且成为了我们团队对工作、生活及寻求内心…

大话设计模式之迪米特法则

迪米特法则&#xff0c;也称为最少知识原则&#xff08;Law of Demeter&#xff09;&#xff0c;是面向对象设计中的一个重要原则&#xff0c;其核心思想是降低耦合度、减少对象之间的依赖关系&#xff0c;从而使系统更加灵活、易于维护和扩展。 根据迪米特法则&#xff0c;一…

CSS之动画

一&#xff0c;动画的制作 实现盒子绕圈走 二&#xff0c; 动画的常用属性 三&#xff0c;动画简写属性 前面两个属性一定要写&#xff0c;第三个linear是指匀速的意思&#xff08;默认是ease&#xff09;

matplotlib中的颜色表示方法

matplotlib中的颜色表示方法 1.RGB或RGBA格式 格式示例以一个3元素或4元素的tuple来表示颜色&#xff0c;每个元素取值范围是[0,1](0.1,0.2,0.5) (0.1,0.2,0.5,0.3)大小写不敏感的16进制表示法#0F0F0F等价于#0x0f0f0f等价于(15/255,15/255,15/255)带透明度的#0f0f0f80简短的…

Qt_day4:2024/3/25

作业1&#xff1a; 完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转到其他界面 如果账号和…

Java毕业设计-基于Spring Boot的在线考试系统-毕业论文+答辩ppt(附源代码+演示视频)

文章目录 前言一、毕设成果演示&#xff08;源代码在文末&#xff09;二、毕设摘要展示1、开发说明2、需求分析3、系统功能结构 三、系统实现展示1、系统登录注册2、管理员功能模块3、用户功能模块 四、毕设内容和源代码获取总结 Java毕业设计-基于Spring Boot的在线考试系统-毕…

Linux之冯诺依曼体系,操作系统,进程的理解,进程状态,以及进程的优先级

个人主页&#xff1a;点我进入主页 专栏分类&#xff1a;C语言初阶 C语言进阶 数据结构初阶 Linux C初阶 算法 欢迎大家点赞&#xff0c;评论&#xff0c;收藏。 一起努力&#xff0c;一起奔赴大厂 目录 一.冯诺依曼体系 二.操作系统 2.1概念 2.2结构示意图&…

面试产品经理,怎样描述过往经历,才能让面试官印象深刻?

金三银四求职季&#xff0c;你是不是也有面试的冲动&#xff01;但面试并不是头脑一热就能取得好结果&#xff0c;在此之前&#xff0c;必须得有周全的准备&#xff0c;才能应对好面试官的“连环问”&#xff01; 所以&#xff0c;给大家分享这篇产品经理面试干货文章&#xf…

搬运5款有趣又好用的软件

​ 如果你想让你的电脑使用更方便、更有趣、更专业&#xff0c;那么你一定要看看这篇文章&#xff0c;因为我要给你推荐五款好用又有趣的WIN10软件。 1. 文字识别——PandaOCR ​ PandaOCR是一款高效的文字识别软件&#xff0c;可快速将图片中的文字转化为可编辑的文本。其识…

2024年MathorCup数学建模思路B题思路分享

文章目录 1 赛题思路2 比赛日期和时间3 组织机构4 建模常见问题类型4.1 分类问题4.2 优化问题4.3 预测问题4.4 评价问题 5 建模资料 1 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 2 比赛日期和时间 报名截止时间&#xff1a;2024…

刚刚,璞华科技、璞华易研PLM产品荣获智能制造领域两大奖项!

刚刚&#xff0c;在e-works数字化企业网于北京举办的“第十三届中国智能制造高峰论坛暨第二十一届中国智能制造岁末盘点颁奖典礼”上&#xff0c;璞华科技凭借在智能制造领域的雄厚实力和产品口碑&#xff0c;荣获两大奖项。 璞华科技被评为e-works【2023年度智能制造优秀供应…

20232831 2023-2024-2 《网络攻防实践》第4次作业

目录 20232831 2023-2024-2 《网络攻防实践》第4次作业1.实验内容2.实验过程&#xff08;1&#xff09;ARP缓存欺骗攻击&#xff08;2&#xff09;ICMP重定向攻击&#xff08;3&#xff09;SYN Flood攻击&#xff08;4&#xff09;TCP RST攻击&#xff08;5&#xff09;TCP会话…

为什么你的企业需要渗透测试

渗透测试是什么&#xff1f; 渗透测试是在安全、符合规定并且受控的条件下针对公司精心策划的经过批准的网络攻击。渗透测试人员努力发现和利用组织环境的设定范围内的漏洞&#xff0c;在黑客等犯罪分子利用它们之前提前分析弱点。 渗透测试通常是安全审计的一部分&#xff0…

大规模云存储展望|2024逐步复苏,2025全面恢复

SSD以其高速度和低延迟等优点&#xff0c;尤其在容量增长和每GB成本降低方面&#xff0c;SSD的增长速度预计将超过近线硬盘&#xff08;Nearline HDD&#xff09;。尽管HDD在大容量存储方面仍有一定优势&#xff0c;但由于SSD在访问速度、能耗及体积等方面的突出表现&#xff0…

fastapi学习记录

今天看了点fastap&#xff0c;简单记录下&#xff0c;fastapi是一个python下的后端框架。 参考学习网站菜鸟教程 安装 pip install fastapi pip install "uvicorn[standard]"安装好了以后就可以直接使用&#xff0c;最主要的使用方式就是写接口嘛&#xff0c;get&a…

FMEA与智能机器人:提升机器人可靠性与安全性的关键

随着科技的飞速发展&#xff0c;智能机器人已经深入到我们生活的方方面面&#xff0c;从工业生产到家庭服务&#xff0c;从深海探险到太空探索&#xff0c;处处都有它们的身影。然而&#xff0c;随着应用的日益广泛&#xff0c;机器人系统的复杂性和不确定性也在增加&#xff0…

速成软件书是神器还是焦虑?

一、背景 "速成软件书"通常是指那些宣称能帮助读者在短时间内掌握某种软件操作或编程技能的书籍。这类书籍往往以其高效、快捷的学习路径吸引读者&#xff0c;尤其适合有一定基础或者急需短期内提升特定技能的人群。 然而&#xff0c;“神器”之称则带有主观性和一…

双端队列deque和vector以及list的优缺点比较

参考:https://blog.csdn.net/TWRenHao/article/details/123483085 一、vector vector具体用法详情点这里 优点&#xff1a; 支持随机访问 CPU高速环缓存命中率很高 缺点&#xff1a; 空间不够&#xff0c;便需要增容。而增容代价很大&#xff0c;还存在一定的空间浪费。 头部…

数据可视化为什么能在智慧港口中发挥作用?

随着全球贸易活动日益频繁&#xff0c;港口作为国际贸易的重要节点&#xff0c;其运营效率与智能化程度直接影响着整个物流链的效能。在此背景下&#xff0c;智慧港口的概念应运而生&#xff0c;它借助先进的信息技术手段对传统港口进行改造升级&#xff0c;其中&#xff0c;数…