3

我们有一个通常的类层次结构:

class B
{
public:
    int x;
    B() : x(0) {}
    virtual ~B() {}
};

class D : public B
{
public:
    int y;
    D() : y(0) {}
};

还有一个接受一个参数的函数 - 对基类对象的引用。

void b_set(B& b)
{
    b.x = 5;
}

然后,我想创建类型的函数指针void (D&)并存储b_set在其中。这应该是有效的操作,因为合法传递给函数指针调用的所有对象也必须是 B 类型。但这是不允许的。

typedef void (*fp_d_mutator)(D&);
void fp_test(D& obj)
{
    fp_d_mutator fun = b_set; //invalid conversion from 'void (*)(B&)' to 'fp_d_mutator {aka void (*)(D&)}
    fun(obj);
}

#include <functional>
typedef std::function<void (D&)> stdfun_d_mutator;
void stdfun_test(D& obj)
{
    stdfun_d_mutator fun = b_set; //works 
    fun(obj);
}

所以...

  • 那无效转换如何?
  • 为什么无效转换?
  • 如果允许这样做会破坏什么?
  • std::function 首先是如何避免这个问题的?
4

1 回答 1

3

接受类型参数的B&函数不是接受类型参数的函数D&。虽然D&转换为 B&,但它们不是同一类型。如果您可以存储指向作为指针的函数B&的指针D&,编译器如何知道何时转换参数?(注意转换有时需要调整指针)

不同之std::function处在于调用签名(此处D&)是函数对象类型的一部分,被调用签名(此处B&)是内部存储的一部分。因此,当您应用函数对象时operator(),实现的代码operator()(D&)会负责转换。

于 2013-03-29T18:20:23.673 回答