在C ++中调用operator()之前,为什么要取消引用指针?

时间:2014-11-22 18:39:33

标签: c++ pointers function-pointers

我正在尝试创建一个通用Distribution类,它包含<random>标头中的许多可用分发。

为了做到这一点,我创建了一个指向派生类内部预期分布的指针(检查下面的代码)。 <random>中的所有发布都实现operator()以根据所考虑的分布获得随机数。如果distribution不是指针,那么我就可以调用distribution(this->randomNumGen)来获取随机数。

但是,我将distribution声明为指针,因此如果我按//THIS LINE绘制一个随机数,则下面标记为distribution(this->randomNumGen)的行将无法编译,并出现以下错误:< / p>

  明显调用的括号前面的

表达式必须具有(指向 - )函数类型

我必须将operator()称为(*this->distribution)(this->randomNumGen)

  • 为什么在调用operator()之前必须取消引用指针?

我有以下标题:

class Distribution_c
{
public:
    Distribution_c(std::mt19937&);
    ~Distribution_c();

    virtual std::vector<double> GetSample(int);

protected:
    std::mt19937 randomNumGen;
};

class UniformDistribution : public Distribution_c
{
public:
    UniformDistribution(double, double, std::mt19937&);
    ~UniformDistribution();
    virtual std::vector<double> GetSample(int);
private:
    double x0;
    double x1;
    std::uniform_real_distribution<double>* distribution; // POINTER TO THE DISTRIBUTION
};

以及以下实施

UniformDistribution::UniformDistribution(double x0, double x1, std::mt19937& rng)
    : Distribution_c(rng)
{
    this->x0 = x0;
    this->x1 = x1;
    this->distribution = new std::uniform_real_distribution<double>(x0, x1);
}
UniformDistribution::~UniformDistribution()
{
    delete this->distribution;
}
std::vector<double> UniformDistribution::GetSample(int N)
{
    std::vector<double> v(N);
    int i = 0;
    while (i < N)
    {
        v.push_back((*this->distribution)(this->randomNumGen)); // THIS LINE
        i++;
    }
}

Distribution_c::Distribution_c(std::mt19937& rng)
{
    this->randomNumGen = rng;
}
std::vector<double> Distribution_c::GetSample(int N)
{
    return std::vector<double>();
}
Distribution_c::~Distribution_c()
{
}

1 个答案:

答案 0 :(得分:2)

  

为什么在调用operator()

之前必须将对象转换为函数指针

你没有,你也不能。它不会起作用。无法将指向对象的指针转换为指向函数的指针。即使这是允许的,也几乎没有意义:通过将对象转换为函数指针并调用它,您将使控制流跳转到对象碰巧所处的任何内存地址。由于它不是一个函数,并且可能不包含合理的可执行代码,因此它将是未定义的行为(并且很可能是崩溃)。

代码

(*this->distribution)

不是转换为函数指针!它只是意味着取消引用指向对象的指针,获取对象本身,您现在可以将其应用于()运营商。

或者,您可以通过使用

直接调用运算符来使您的意图更加清晰并强调您有一个带有重载调用运算符的函数对象。
distribution->operator()(randomNumGen);

此表示法将运算符视为普通的非静态成员函数(称为operator()),并相应地对其进行参数化。