函数指针和访问-为什么这个代码是合法的

Function Pointers and Access - Why is this code legal?

本文关键字:代码 指针 访问 为什么 函数      更新时间:2023-10-16

我最近遇到了一些让我惊讶的事情,如果能澄清一下就好了。

假设我有一个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);
    }
    //...
};

以及如下的类别CCD_ 2:

#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主体中的函数,因为Aupdate_routineprivate成员函数,因此我认为试图从B调用它会导致inaccessible method错误或类似的错误,即使它是作为函数指针传递的。

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

p.S:如果这是重复的,我很抱歉,如果是这样的话,请链接相关主题。

术语public和private(以及protected)实际上只指事物的名称——名称update_routine是私有的,只能解析为类范围内的实际函数。由于您只在类的作用域内使用名称,因此没有问题。

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类。您正在取消引用中的fptrupdate_quantity功能,但原型对于fptr没有任何对A类,因此不存在来自B类至A.

update_routine的地址可能作为函数指针参数-但A函数仍然没有直接编码在B类中,正如所写的那样。换句话说,如果函数指针只是一个参数,那么取消引用该函数指针参数并不一定会导致类特权冲突。

fptrupdate_quantity的严格局部,不被认为是A类的一部分。。

它是从A内部传递的,在那里它非常明显。可见性不会更改函数的类型。如果您试图从B::update_quantity调用A::update_routine,这将是非法的。但A已经将地址赋予了B,并将函数调用委托给了它。同时,B不知道它接收到什么函数地址。