功能指针和访问 - 为什么此代码合法?

时间:2016-04-09 22:38:09

标签: c++ function-pointers private-members

我最近遇到了让我感到惊讶的事情,对它进行一些澄清很高兴。

假设我有一个由A组成的课程,其中包含以下内容:

#include "B.h"

class A {

private:
    B* inst_b;
    std::mt19937 mt_eng; 

    static void update_routine(double& _p, std::mt19937& _eng) {
        // does stuff, not important here
    }

public:
    A() {
        std::random_device rd;
        mt_eng = std::mt19937(rd());
    }

    void updateP() {
        inst_b->update_quantity(update_routine, mt_eng);
    }

    //...
};

和类B如下:

#include <random>

class B {

protected:
    double qty; 
    //...
public:
    B() {
        qty = 0.0;
    }

    void update_quantity(void(*fptr)(double&, std::mt19937&), std::mt19937& _eng) {
        fptr(qty, _eng); // no error here
    }

    //...
};

现在我认为编译器会抱怨尝试在update_quantity的主体中调用该函数,因为update_routine的{​​{1}}是A成员函数,因此我认为尝试从private调用它会导致B错误或类似的东西 - 即使它已作为函数指针传递。

在我的项目中,当我执行上述操作时,它会成功编译并执行 - 这是为什么?当然,对我来说非常有用,它确实 编译并运行但是我想了解为什么会这样。

P.S:如果这是重复的话,我表示歉意,如果是这种情况,请链接相关主题。

3 个答案:

答案 0 :(得分:2)

术语public和private(和protected)实际上只引用事物的名称 - 它是私有的名称update_routine,只能解析为类范围内的实际函数。由于您只使用了班级范围内的名称,因此没有问题。

答案 1 :(得分:1)

它从A内部传递,在那里它是非常明显的。可见性不会改变功能的类型。 如果您尝试从A::update_routine拨打B::update_quantity,这将是非法的。但是A给了B地址并委托函数调用它。同时B不知道它收到的函数地址。

答案 2 :(得分:1)

class B {

protected:
    double qty; 
public:
    B() {
        qty = 0.0;
    }

    void update_quantity(void(*fptr)(double&, std::mt19937&), std::mt19937& _eng) {
        fptr(qty, _eng); // no error here
    }

};

上述代码中没有引用A类。 您正在取消引用中的fptr update_quantity功能,但原型 对fptr没有任何引用 A类 - 所以没有特权违规 B级到A级。

update_routine的地址可能会作为一个传递 函数指针参数 - 但A函数仍未直接编码在B类中,如所写。换句话说,如果函数指针只是一个参数,那么取消引用此函数指针参数不一定会导致类特权违规。

fptr严格来说属于update_quantity,并且不属于A类的一部分..