当前位置:首页 » 《关注互联网》 » 正文

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

28 人参与  2024年04月03日 15:05  分类 : 《关注互联网》  评论

点击全文阅读


目录

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 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://zhangshiyu.com/post/90099.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

最新文章

  • 全文潮痕蚀月光(池清禾***宸)列表_全文潮痕蚀月光
  • 「江月随人处处圆」小说无删减版在线免费阅读_[陆晨小姐孟苒]精彩章节免费试读
  • 阮雾梨闻砚辞阮见微结局+番外全书+后续+结局(闻砚辞阮雾梨)列表_阮雾梨闻砚辞阮见微结局+番外(闻砚辞阮雾梨)阮雾梨闻砚辞阮见微结局+番外全书+后续+结局在线
  • 潮痕蚀月光结局+番外池清禾***宸(潮痕蚀月光结局+番外)全书免费池清禾***宸_潮痕蚀月光结局+番外池清禾***宸列表_笔趣阁(池清禾***宸)
  • 苔藓爬满旧日诺言一口气读完全书+后续全书+后续+结局(慕晚夏顾砚廷)列表_苔藓爬满旧日诺言一口气读完全书+后续(慕晚夏顾砚廷)苔藓爬满旧日诺言一口气读完全书+后续全书+后续+结局在线
  • 「孕弟」反转剧情碎片化试读_[耀祖弟弟子宫]小说精彩节选试读
  • 旧梦随风去结局+番外(姜予宁沈昭寒)列表_旧梦随风去结局+番外(姜予宁沈昭寒)全书+后续+结局在线
  • (番外)+(全书)佛心不渡红尘劫+后续+结局(云狸越渊)全书在线_佛心不渡红尘劫+后续+结局免费列表_笔趣阁(云狸越渊)
  • 给你的第三封信是遗言沈佳芮顾温言_给你的第三封信是遗言沈佳芮顾温言列表
  • 闻砚辞阮雾梨(许是曾经有相思人面桃花长相忆+番外)_(闻砚辞阮雾梨)许是曾经有相思人面桃花长相忆+番外列表_笔趣阁(闻砚辞阮雾梨)
  • 男友让我给白月光顶罪后我杀疯了人气小说未删减节选_苏泽裴婉婷王希谣全文+后续
  • 慕晚夏顾砚廷顾砚廷

    关于我们 | 我要投稿 | 免责申明

    Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1