当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《std::bind是否在C++11中丢弃了参数的类型信息?》经验,为你挑选了1个好方法。

出现问题的情况

请考虑以下c ++代码:

#include 
#include 
#include 

// 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();
}

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

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

该类State包含对实例的引用A.该类还有一个简单的方法,可以print通过两种不同的方式调用.

奇怪的地方

状态中唯一的方法是print直接调用.由于我们B在main方法中提供了int 实例,因此输出It's B正如预期的那样.

但是,对于第二个调用,我们将实例绑定到printusing 的第一个参数std::bind.然后我们调用结果函数而不带任何参数.

但是,在这种情况下,输出是It's A.我会It's B像以前一样期望输出,因为它仍然是同一个实例.

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

为什么会这样?std::bind在这种情况下会丢弃某些类型的信息吗?根据我的理解,这不应该发生,因为方法调用应该通过运行时的vtable查找来管理.



1> Kerrek SB..:

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

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

为了解释这一点:与大多数C++标准库类型一样,bind表达式的结果类型拥有其所有绑定状态.这意味着您可以获取此值并自由传递并存储它,稍后在不同的上下文中返回它,您仍然可以在其所有绑定状态准备好进行操作时调用它.

因此,在您的代码中,绑定对象是使用的副本构造的instance.但由于instance不是一个完整的对象,你导致切片发生.

相比之下,我的代码将a复制std::reference_wrapper到绑定对象中,而这实际上是一个指针.它不拥有实例对象,因此只要可以调用绑定对象,我就需要保持活动状态,但这意味着绑定调用将以多态方式分派给整个对象.


@Emiswelt:神奇的问题是"它是什么*".*毫无疑问,有些东西是通过参考传递的,但不是你的想法.在您的情况下,绑定对象本身包含您的实例的*切片副本*(它通过引用正式传递),而在我的代码中它包含一个引用包装器.
推荐阅读
黄晓敏3023
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有