std::bind 是否丢弃 C++11 中参数的类型信息?

2023-12-08

问题发生的情况

请考虑以下 C++ 代码:

#include <functional>
#include <iostream>
#include <string>

// Superclass
class A {
    public:
    virtual std::string get() const {
        return "A";
    }
};

// Subclass
class B : public A {
    public:
    virtual std::string get() const {
        return "B";
    }
};

// Simple function that prints the object type
void print(const A &instance) {
    std::cout << "It's " << instance.get() << std::endl;
}

// Class that holds a reference to an instance of A
class State {
    A &instance;
    public:
    State(A &instance) : instance(instance) { }
    void run() {

        // Invokes print on the instance directly
        print(instance);

        // Creates a new function by binding the instance
        // to the first parameter of the print function, 
        // then calls the function. 
        auto func = std::bind(&print, instance);    
        func();
    }    
};

int main() {
    B instance;
    State state(instance);

    state.run();
}

在这个例子中,我们有两个类A and B. B从类继承A。这两个类都实现了一个返回类型名称的简单虚拟方法。

还有一个简单的方法,print,它接受对实例的引用A并打印类型。

班上State持有对实例的引用A。该类还有一个简单的方法,调用print通过两种不同的方式。

哪里变得奇怪

状态中唯一的方法首先调用print直接地。由于我们提供了一个实例Bint main 方法,输出是It's B,正如预期的那样。

然而,对于第二次调用,我们将实例绑定到第一个参数print using std::bind。然后我们不带任何参数调用结果函数。

然而,在这种情况下,输出是It's A。我本来期望输出It's B,和以前一样,因为它仍然是同一个实例。

如果我将参数声明为指针而不是引用,std::bind按预期工作。我还在两个类的构造函数中放置了一些日志记录,以验证没有意外创建实例。

为什么会出现这种情况?做std::bind在这种情况下丢弃一些类型信息?据我了解,这种情况一定不会发生,因为方法调用应该由运行时的 vtable 查找来管理。


这只是对象切片。通过引用传递实例:

auto func = std::bind(&print, std::ref(instance));
//                            ^^^^^^^^

进一步解释一下:像大多数 C++ 标准库类型一样,a 的结果类型bind表达owns它的所有束缚态。这意味着您可以获取该值并自由传递它并存储它并稍后在不同的上下文中返回它,并且您仍然可以在其所有绑定状态准备好执行操作的情况下调用它。

因此,在您的代码中,绑定对象是用copy of instance。但是由于instance不是一个完整的对象,你导致了切片的发生。

相比之下,我的代码复制了一个std::reference_wrapper<A>到绑定对象中,这本质上是一个指针。它不拥有实例对象,因此只要可以调用绑定对象,我就需要使其保持活动状态,但这意味着绑定调用会以多态方式分派到完整的对象。

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

std::bind 是否丢弃 C++11 中参数的类型信息? 的相关文章

  • 简单的 C++ 线程

    我正在尝试在 C Win32 中创建一个线程来运行一个简单的方法 我是 C 线程的新手 但对 C 中的线程非常熟悉 这是我想做的一些伪代码 static void MyMethod int data RunStuff data void R
  • HttpResponseMessage 的内容为 JSON

    我有一个 ASP NET MVC WEB API 由于多种原因 由于没有授权而重定向 我不能只使用一个简单的对象并在我的控制器方法中返回它 因此我需要 HttpResponseMessage 类来允许我重定向 目前我正在这样做 var re
  • 无法在更新面板中找到上传的文件

    aspx
  • 对相当大的整数的大集合的操作的快速实现

    描述 我实现了以下类 LabSetInt64 参见下面的代码 这里的目标是尽可能快地操作大量大整数 最多 10M 的值 我的主要要求集中在 至关重要 尽快获取集合的大小 基数 重要 能够非常快速地迭代一组集合 所以 从下面的实现开始 我还有
  • 按位非运算符

    为什么要按位运算 0 打印 1 在二进制中 不是0应该是1 为什么 你实际上很接近 在二进制中 不是0应该是1 是的 当我们谈论一位时 这是绝对正确的 然而 一个int其值为0的实际上是32位全零 将所有 32 个 0 反转为 32 个 1
  • 有哪些 API 可在 Windows 中使用 C# 配置扬声器设置?

    我环顾了很多不同的地方 但似乎找不到一个简单的方法来做到这一点 我在 Windows 7 中有多个声卡 并使用 HDMI 将声音输出到我的 AVR 放大器 我遇到的问题是 当放大器关闭时 它会导致窗口丢失扬声器配置 所以我想做的是编写一个小
  • .NET 中 IEqualityComparer 中 GetHashCode 的作用是什么?

    我试图了解 IEqualityComparer 接口的 GetHashCode 方法的作用 下面的例子取自MSDN using System using System Collections Generic class Example st
  • 整数与双精度算术性能?

    我正在编写一个 C 类来使用整数执行 2D 可分离卷积 以获得比双对应更好的性能 问题是我没有获得真正的性能提升 这是 X 过滤器代码 对于 int 和 double 情况都有效 foreach pixel int value 0 for
  • 了解 MVC-5 身份

    我创建了一个新的ASP NET MVC 5申请与Individual User Accounts然后更新了所有的Nuget packages在解决方案中 现在我尝试遵循一些教程中显示的一些指南 但遇到了一些问题 第一个是一个名为Applic
  • 使用 MapViewOfFile 有什么限制吗?

    我正在尝试将内存映射文件用作 hFile CreateFile State Path GENERIC READ FILE SHARE READ FILE SHARE WRITE 0 OPEN EXISTING FILE FLAG SEQUE
  • 编译器在函数名称前添加下划线前缀的原因是什么?

    当我看到 C 应用程序的汇编代码时 如下所示 emacs hello c clang S O hello c o hello s cat hello s 函数名称以下划线作为前缀 例如callq printf 为什么这样做以及它有什么优点
  • MPI_Gatherv:根数组中收到的垃圾值

    我正在尝试实施MPI Gatherv函数于C 根据我的程序 包括 root 在内的每个进程都应该创建一个大小等于 进程的等级 1 这将在所有单元格中保持进程的等级 然后这个本地数组被收集到根的 rcv array 中 不知何故 我得到了垃圾
  • 如何从句柄确定进程是 32 位还是 64 位?

    如何从使用 OpenProcess 获取的进程句柄中获取信息 无论进程是 32 位还是 64 位 是的 IsWow64Process 毫无用处 令人烦恼 它的真正意思是 启用了 32 位模拟 如果您在 32 位操作系统上运行 则返回 fal
  • C# 编译器编译 .txt .obj .java 文件

    using System class Program public static void Main Console WriteLine Hello World Console ReadLine 我将文件另存为1 java 2 obj an
  • 检测用户是否正在滚动 dataGridView 滚动条

    我正在更新一个dataGridView与一个新的数据表使用 dataGridView1 DataSource table 但是 我不想在用户滚动 dataGridView 时执行此操作 如何检查滚动条是否正在滚动或已完成滚动 即拖动而不是单
  • RabbitMQ + Windows + LDAP 无需发送密码

    我正在尝试在 Windows 7 上使用 RabbitMQ 3 6 2 进行 LDAP 身份验证 授权 我已经在应用程序发送用户名 密码的情况下进行了基本身份验证 但密码位于我需要弄清楚如何进行的代码中避免 有没有人在不提供密码的情况下成功
  • 没有运算符“<<”与这些操作数匹配[重复]

    这个问题在这里已经有答案了 不知道发生了什么事 我查看了与此问题类似的其他帖子 但到目前为止没有解决方案有帮助 这是带有错误部分注释的代码 在某一时刻 它说 不起作用 而在代码的其余部分中 它说 include
  • 如何通过Task.ContinueWith创建传递?

    我想在原始任务结束时添加一个任务 但想保留原始结果和类型 附加任务仅用于记录目的 例如写入控制台等 例如 Task Run gt DateTime Now Hour gt 12 Hey throw new Exception Continu
  • 为什么 32 位 .NET 进程的引用类型的最小大小为 12 字节

    我正在读专业 Net 性能 https rads stackoverflow com amzn click com 1430244585本书有关参考类型内部结构的部分 它提到 对于 32 位 net 进程 引用类型具有 4 字节的对象头和
  • “保留供任何使用”是什么意思?

    注意 这是一个c questions tagged c问题 虽然我补充说c questions tagged c 2b 2b如果某些 C 专家可以提供 C 使用与 C 不同的措辞的基本原理或历史原因 在 C 标准库规范中 我们有这个规范文本

随机推荐

  • 可编辑标签控件

    有谁知道我如何创建可编辑标签控件 我需要我的用户能够编辑标签 还可以更改其样式信息的部分 但在网上找不到任何有用的信息 如有任何帮助 我们将不胜感激 谢谢 您可以创建自定义控件 需要一些工作 该控件内部可以有一个标准标签控件 当用户单击该标
  • 斯坦福 NER:我可以在代码中同时使用两个分类器吗?

    在我的代码中 我得到Person来自第一个分类器的识别 对于我制作的第二个分类器 我添加了一些要识别或注释的单词组织但它没有注释Person 我需要从他们两个那里得到好处 我该怎么做呢 我正在使用 Netbeans 这是代码 String
  • 调用Web服务时出错

    我无法致电web service即使添加后kSOAP 2 library jar file 源代码 package com example web import org ksoap2 SoapEnvelope import org ksoa
  • MonadException 实例未推导

    也许我在这里做了一些愚蠢的事情 但我得到 No instance for MonadException Ti arising from a use of getInputLine 在代码示例中 module Foo where import
  • Tornado - 通过 websocket 同时监听多个客户端

    我想使用 Tornado 在 Python 中创建 websocket 服务器 这是 API http tornado readthedocs org en latest websocket html 在 API 中 我没有看到获取客户端句
  • Apache .htaccess // 设置为禁止子文件夹文件

    我对 Apache htaccess 感到抓狂 我试图使用相对地址将我的子文件夹设置为受保护 但这似乎不可能 Apache文件夹的路径结构如下 var www apachedir 现在我想保护 var www apachedir subfo
  • 属性 httpRequest' 不存在

    当我在 Visual Studio 外部运行构建时收到此错误 名称为 httpRequest 的属性不存在 如果我在 Visual Studio 中运行相同的代码 它就会起作用 有人知道我做错了什么吗 我的应用程序配置
  • 方法 vs 基本 JS?我应该使用 toString 吗?解析Int? jQuery?

    自从我发现 toString 函数以来 这是我一直想知道的一个问题 但从未费心去问 我应该使用基本的 JS 还是做同样事情的函数 现在 不要误会我的意思 我意识到 toString 有其可取之处 就像将函数转换为字符串一样 var mess
  • PHP:如何用逗号分解字符串,而不是逗号在引号内的位置?

    我需要将字符串输入分解为逗号处的数组 但是该字符串在引号内包含逗号 Input line TRUE 59 A large number is 10 000 linearray explode line linemysql implode l
  • Android 使用 RSA 公钥加密字符串

    我正在从事一个必须使用 RSA 公钥加密密码的项目 我尝试了很多来自SO的示例和解决方案 如下所示 来自公共字符串的 Android RSA 加密 使用 SpongyCastle 进行 RSA 但不幸的是 这些解决方案都不适用于我的情况 如
  • 在 JSON.parse() 之后保留属性属性(可写、可配置)

    假设我正在其他地方创建一个对象并以某种方式将其传递到我的模块 也许它是在服务器上创建的node js 也许它是在不同的模块中创建的 无论出于何种原因我JSON stringify 解析它并传递序列化版本 特别是如果它来自服务器 但我希望这个
  • 禁用 PictureBox 上的图像混合

    在我的 Windows 窗体程序中 我有一个PictureBox包含一个小图像 5 x 5 pixels 当这个位图被分配给PictureBox Image属性 它变得非常模糊 我试图找到诸如混合模式 模糊模式或抗锯齿模式之类的东西 但我没
  • 创建新用户集realmRoles时 - Keycloak Admin REST API

    我在创建用户时分配现有领域角色时遇到问题 创建新用户时遵循文档POST realm users 在主体参数中使用UserRepresentation 我们有一个名为realmRoles这是可选的 我已经尝试在以下模式中进行分配 id 123
  • pip install Upgrade 升级私有依赖失败

    背景 pip支持ssh链接后缀 分店名称 提交哈希值 标签名称 一个 git 参考 但是 pip 在升级某些依赖于这些 ssh 链接的软件包时存在问题 在版本 5 1 2 的名为 CurrentPackage 的包的 setup py 中
  • Meteor/Semantic-UI 中的错误?

    如果根元素是流星模板 则语义 UI 模态窗口的使用不起作用 包 semantic ui css 错误重现 你好 html
  • UITableView willDisplayCell 方法的错误行为

    有一个UITableView的帖子 看到的帖子 id 保存在 sqlite 中我想用橙色显示已看过的帖子 用黑色显示其他帖子 但是当我为看到的帖子设置橙色时willDisplayCell方法某些单元格被错误地着色为橙色 否则打印日志 为其着
  • com.mysql.jdbc.driver类未找到异常

    我得到了帮助this博客文章 但我得到 com mysql jdbc driver 类未找到异常 该博客文章的不同之处在于 在我的例子中 他们尝试连接到 mysql 而不是 MS SQL 到目前为止 这是我的代码 包com example
  • Arduino 安卓 USB 连接

    我正在使用 Arduino杜米拉诺夫 and Nexus 7 我已成功检测到 Arduino 板并显示供应商 ID 和产品 ID 我正在尝试将数据从平板电脑传输到 Arduino 板并尝试闪烁LED在黑板上 Android 的代码如下 主要
  • UIWebView 只有一个应该适合整个视图的图像

    所以我现在遇到的问题是 UIWebViews 显示单个图像 我想要的是 如果图像不适合该位置 则缩小图像 如果不适合 则保持其原始大小 所以这是我的做法 在 UIViewController 中 void viewDidLoad super
  • std::bind 是否丢弃 C++11 中参数的类型信息?

    问题发生的情况 请考虑以下 C 代码 include