成员函数指针从派生类到基类的强制转换

2024-01-09

我正在执行以下操作:

  • 获取成员函数指针3 params from a 派生类.
  • 将其转换为成员函数指针基类 with 0 params.
  • 将其投射到基类 with 3个参数 back.
  • 呼唤着它。

它工作得很好(到目前为止),但我应该保留它吗?

当前代码说明:

EventsWarehouse用于存储和调用事件:

#include <iostream>
#include <functional>
#include <unordered_map>

class EventsWarehouse
{
public:
    typedef std::tuple<AView*, void (AView::*)()>           box_t;
    typedef std::unordered_multimap<std::string, box_t>     boxes_t;

    void        storeEvent(std::string const &event, AView *v, void (AView::*callback)())
        {
            this->_events.insert(std::make_pair(event, std::make_tuple(v, callback)));
            return ;
        }

    template<typename... Args>
    bool        fireEvent(std::string const &event, Args... args)
        {
            auto                it = this->_events.find(event);
            AView               *v;
            void                (AView::*callback_)();
            void                (AView::*callback)(Args...);

            for (; it != this->_events.end(); it++)
            {
                v = std::get<0>(it->second);
                callback_ = std::get<1>(it->second);
                /*
                ** CAST #2
                ** <void (AView::*)()>
                **  to
                ** <void (AView::*)(std::string, int, double)>
                **  before call
                */
                callback = reinterpret_cast<void (AView::*)(Args...)>(callback_);
                (v->*callback)(args...);
            }
            return (true);
        }
private:
    boxes_t         _events;

};

查看上面类中存储的类:

class AView
{
protected:
    AView(){}
};

class DerivedView : public AView
{
public:
    void    fooCallback(std::string s, int i, double d)
        {
            std::cout << "DerivedView::fooCallback received " << s << ", " << i << ", " << d << std::endl;
            return ;
        }
};

Main:

int                         main(void)
    {
        DerivedView     dv;
        EventsWarehouse ewh;

        /*
        ** CAST #1
        ** <void (DerivedView::*)(std::string, int, double)>
        **  to
        ** <void (AView::*)()>
        **  for storing purpose
        */
        ewh.storeEvent("event 1", &dv, reinterpret_cast<void (AView::*)()>(&DerivedView::fooCallback));
        ewh.fireEvent("event 1", std::string("Hello World"), 42, 84.42);
        return (0);
    }

根据 C++11 规范草案 n4296,5.2.10 重新解释强制转换 [expr.reinterpret.cast] §10

如果 T1 和 T2 都是函数类型或都是对象类型,则“指向 T1 类型 X 成员的指针”类型的纯右值可以显式转换为不同类型“指向 T2 类型 Y 成员的指针”的纯右值。 72 null 成员指针值 (4.11) 转换为目标类型的 null 成员指针值。此转换的结果未指定,但以下情况除外:

— 将“指向成员函数的指针”类型的纯右值转换为不同的指向成员函数的指针 类型并返回其原始类型会产生指向成员值的原始指针。

— 将“指向 T1 类型 X 的数据成员的指针”类型的纯右值转换为“指向数据的指针”类型 T2 类型 Y 的成员”(其中 T2 的对齐要求不比 T1 严格) 并返回其原始类型,产生指向成员值的原始指针。 转换为指向不带参数的成员函数的指针并返回到具有正确参数的成员函数应该返回原始指针。

恕我直言,问题是fooCallback仅定义于DerivedView类,因此它是not类的成员函数AView.

这是正确的:

void (AView::*p)() = reinterpret_cast<void (AView::*)()>(&DerivedView::fooCallback);
void (DerivedView::*callback)(std::string, int, double) =
       reinterpret_cast<void (DerivedView::*)(std::string, int, double)>(p);
v->callback("Hello World"), 42, 84.42);

假如v is a AView *指向一个DerivedView

但是当你结束转换时void (DerivedView::*)(std::string, int, double) to a void (AView::*)(std::string, int, double)它们是不同的类型,因此未指定转换

它有效,因为非静态非虚拟成员函数的常见实现只是一个普通(非成员)函数,其隐藏参数为this。因此,指向成员的指针仅存储该函数的地址,并使用指向 a 的指针正确调用它DerivedView给出预期的结果。但不同的实现也可以存储实际类型并引发异常(或执行其他操作)。

TL/DR:当你以从void (DerivedView::*)(std::string, int, double) to void (AView::*)(std::string, int, double)您不会将指向成员的指针转换为其原始类型并调用未定义的行为。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

成员函数指针从派生类到基类的强制转换 的相关文章

  • GLKit的GLKMatrix“列专业”如何?

    前提A 当谈论线性存储器中的 列主 矩阵时 列被一个接一个地指定 使得存储器中的前 4 个条目对应于矩阵中的第一列 另一方面 行主 矩阵被理解为依次指定行 以便内存中的前 4 个条目指定矩阵的第一行 A GLKMatrix4看起来像这样 u
  • 按成员序列化

    我已经实现了template
  • BitTorrent 追踪器宣布问题

    我花了一点业余时间编写 BitTorrent 客户端 主要是出于好奇 但部分是出于提高我的 C 技能的愿望 我一直在使用理论维基 http wiki theory org BitTorrentSpecification作为我的向导 我已经建
  • OleDbDataAdapter 未填充所有行

    嘿 我正在使用 DataAdapter 读取 Excel 文件并用该数据填充数据表 这是我的查询和连接字符串 private string Query SELECT FROM Sheet1 private string ConnectStr
  • WCF 中 SOAP 消息的数字签名

    我在 4 0 中有一个 WCF 服务 我需要向 SOAP 响应添加数字签名 我不太确定实际上应该如何完成 我相信响应应该类似于下面的链接中显示的内容 https spaces internet2 edu display ISWG Signe
  • 显示UnityWebRequest的进度

    我正在尝试使用下载 assetbundle统一网络请求 https docs unity3d com ScriptReference Networking UnityWebRequest GetAssetBundle html并显示进度 根
  • 如何设计以 char* 指针作为类成员变量的类?

    首先我想介绍一下我的情况 我写了一些类 将 char 指针作为私有类成员 而且这个项目有 GUI 所以当单击按钮时 某些函数可能会执行多次 这些类是设计的单班在项目中 但是其中的某些函数可以执行多次 然后我发现我的项目存在内存泄漏 所以我想
  • Windows 窗体:如果文本太长,请添加新行到标签

    我正在使用 C 有时 从网络服务返回的文本 我在标签中显示 太长 并且会在表单边缘被截断 如果标签不适合表单 是否有一种简单的方法可以在标签中添加换行符 Thanks 如果您将标签设置为autosize 它会随着您输入的任何文本自动增长 为
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • 向现有 TCP 和 UDP 代码添加 SSL 支持?

    这是我的问题 现在我有一个 Linux 服务器应用程序 使用 C gcc 编写 它与 Windows C 客户端应用程序 Visual Studio 9 Qt 4 5 进行通信 是什么very在不完全破坏现有协议的情况下向双方添加 SSL
  • 通过指向其基址的指针删除 POD 对象是否安全?

    事实上 我正在考虑那些微不足道的可破坏物体 而不仅仅是POD http en wikipedia org wiki Plain old data structure 我不确定 POD 是否可以有基类 当我读到这个解释时is triviall
  • cmake 将标头包含到每个源文件中

    其实我有一个简单的问题 但找不到答案 也许你可以给我指一个副本 所以 问题是 是否可以告诉 cmake 指示编译器在每个源文件的开头自动包含一些头文件 这样就不需要放置 include foo h 了 谢谢 CMake 没有针对此特定用例的
  • 如何将带有 IP 地址的连接字符串放入 web.config 文件中?

    我们当前在 web config 文件中使用以下连接字符串 add name DBConnectionString connectionString Data Source ourServer Initial Catalog ourDB P
  • 测试用例执行完成后,无论是否通过,如何将测试用例结果保存在变量中?

    我正在使用 NUNIT 在 Visual Studio 中使用 Selenium WebDriver 测试用例的代码是 我想在执行测试用例后立即在变量中记录测试用例通过或失败的情况 我怎样才能实现这一点 NUnit 假设您使用 NUnit
  • 是否可以在 .NET Core 中将 gRPC 与 HTTP/1.1 结合使用?

    我有两个网络服务 gRPC 客户端和 gRPC 服务器 服务器是用 NET Core编写的 然而 客户端是托管在 IIS 8 5 上的 NET Framework 4 7 2 Web 应用程序 所以它只支持HTTP 1 1 https le
  • C# 模拟VolumeMute按下

    我得到以下代码来模拟音量静音按键 DllImport coredll dll SetLastError true static extern void keybd event byte bVk byte bScan int dwFlags
  • 如何将服务器服务连接到 Dynamics Online

    我正在修改内部管理应用程序以连接到我们的在线托管 Dynamics 2016 实例 根据一些在线教程 我一直在使用OrganizationServiceProxy out of Microsoft Xrm Sdk Client来自 SDK
  • C# - OutOfMemoryException 在 JSON 文件上保存列表

    我正在尝试保存压力图的流数据 基本上我有一个压力矩阵定义为 double pressureMatrix new double e Data GetLength 0 e Data GetLength 1 基本上 我得到了其中之一pressur
  • 使用.NET技术录制屏幕视频[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一种方法可以使用 NET 技术来录制屏幕 无论是桌面还是窗口 我的目标是免费的 我喜欢小型 低
  • 对来自流读取器的过滤数据执行小计

    编辑问题未得到解答 我有一个基于 1 个标准的过滤输出 前 3 个数字是 110 210 或 310 给出 3 个不同的组 从流阅读器控制台 问题已编辑 因为第一个答案是我给出的具体示例的字面解决方案 我使用的实际字符串长度为 450 个

随机推荐

  • 解析 SDK 1.7.1 无法在 Xcode 6.3 中工作

    我的代码在 Xcode 6 2 中运行良好 更新到 Xcode 6 3 后 我遇到了一些 Nullabilty 错误 下载 Parse SDK 1 7 1 后 我可以解决这些错误 所以我删除了项目中旧的 Parse 框架文件并将新的粘贴到其
  • 将浮点数转换为无符号整数,同时保留顺序

    我找到了很多关于 SO 的答案 专注于转换float to int 我只处理正浮点值 我一直在使用的一种简单方法是 unsigned int float2ui float arg0 float f arg0 unsigned int r u
  • 设计 RESTful 登录服务

    我经历过类似的问题here https stackoverflow com questions 4608225 how do i implement login in a restful web service 但我还不清楚概念 这是我的场
  • Spark 使用数据局部性吗?

    我正在尝试了解 Apache Spark 的内部结构 我想知道 Spark 是否使用某些机制来确保从 InputFormat 读取或写入 OutputFormat 或 Spark 本机支持的其他格式而不是从 MapReduce 派生的格式
  • System.NotSupportedException - 无法比较“System.Linq.IQueryable”类型的元素

    我目前收到以下错误 gt EntityFramework SqlServer dll 中发生 System NotSupportedException 类型的异常 但未在用户代码中处理 其他信息 无法比较 System Linq IQuer
  • python selenium 将密钥发送到只读文本框

    我正在尝试使用下面的 python selenium 代码将密钥发送到下面的字段
  • 单行删除重复项,保持列表的排序[重复]

    这个问题在这里已经有答案了 我有以下清单 Herb Alec Herb Don 我想在保持顺序的同时删除重复项 所以它是 Herb Alec Don 以下是我详细地执行此操作的方法 l new for item in l old if it
  • 如何在 r2dbc 中连接表?

    在java反应器中 r2dbc 我有两个表 A B 我还为它们定义了存储库 如何获取A连接B组成的数据 我只提出以下方法 从 A 调用databaseClient select 然后在循环中从 B 调用 select 但我想要更有效和反应性
  • 如何将浮点数转换为字符串而不考虑区域设置?

    我的产品面向葡萄牙受众 其中逗号是小数点符号 我通常使用 CString Format 将数字输入字符串 它会考虑计算机的区域设置 虽然总的来说这是一个很好的方法 但我在格式化 SQL 查询时遇到了问题 例如 CString szInser
  • PL/Python 和 postgreSQL:返回多列表的最佳方法是什么?

    在 Pl Python 中 RETURNS setof 或 RETURNS table 子句用于返回类似结构化数据的表 在我看来 必须提供每一列的名称才能返回表 如果您有一个包含几列的表格 那么这很容易 但是 如果您有一个包含 200 列的
  • 如何将多列连接成单列(事先不知道其数量)?

    假设我有以下数据框 agentName original dt parsed dt user text qwertyuiop 0 0 16102 0 0 我希望创建一个新的数据框 其中多一列 该列连接了该行的所有元素 agentName o
  • 用 python 求解超越方程组

    假设我有以下四个方程 cos x x a 余弦 y y b a b 1 c sinc x d sinc y 对于未知变量x y a and b 注意cos x x a有多种解决方案 变量也类似y 我只感兴趣x and y值 首先是正根 如果
  • CSS“框架”可以解释浏览器的异常情况吗?

    我为一家小型媒体公司建立网站 不幸的是 我们大约 45 50 的客户群使用 IE6 而另一半则几乎均等地使用 Firefox 和基于 Webkit 的浏览器 还有少数 Opera 用户 我的每一个网站都使用类似于 Eric Meyer 的重
  • 如何从多个嵌套if条件调用json

    我正在使用 CodeIgniter 我正在研究一个小项目 它是一个批次列表 现在 如果管理员想要创建批次列表 那么应该输入开始日期和结束日期以及开始时间和结束时间 然后它将在数据库中检查批次是否在相同的日期和时间运行 如果是 那么它将显示该
  • Ruby regexp:捕获url的路径

    我想从任何 URL 中提取其路径 例如 URL https stackoverflow com questions ask https stackoverflow com questions ask路径 问题 提问 这应该不难 url w
  • 场景中有多个反射器:如何实现clone()函数?

    我需要大约 80 移动 反射ShapeBufferGeometry在一个场景中 我希望他们分享尽可能多的材料数据 显然 clone 该方法不适用于Reflector 我得到的黑色几何图形不反射任何东西 尝试添加一个clone 方法到prot
  • Python ABC:注册与子类化

    我使用的是 python 2 7 python 文档表明您可以将映射传递给内置的 dict 它将将该映射复制到新的 dict 中 http docs python org library stdtypes html mapping type
  • 在 OS X El Capitan 10.11 中复制 root 下的文件失败

    我正在尝试将根文件复制到 System 文件夹中 它适用于所有以前的 OS X 版本 但不适用于 El Capitan 10 11 这是我在终端的根目录下复制文件的方法 MACMINI myusername sudo su MACMINI
  • Django 通过多对多中间表中的多个字段进行过滤

    我的 django 项目中有以下模型 class Video models Model media models ForeignKey Media class Media models Model title models CharFiel
  • 成员函数指针从派生类到基类的强制转换

    我正在执行以下操作 获取成员函数指针3 params from a 派生类 将其转换为成员函数指针基类 with 0 params 将其投射到基类 with 3个参数 back 呼唤着它 它工作得很好 到目前为止 但我应该保留它吗 当前代码