C++ 函数指针和访问-为什么该代码是合法的?

C++ 函数指针和访问-为什么该代码是合法的?,c++,function-pointers,private-members,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 } pub

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

假设我有一个类
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
    }

    //...
};
#包括
B类{
受保护的:
双倍数量;
//...
公众:
B(){
数量=0.0;
}
作废更新数量(作废(*fptr)(双重和,标准::mt19937和),标准::mt19937和工程){
fptr(数量,_eng);//此处无错误
}
//...
};
现在我原以为编译器会抱怨试图调用
update\u quantity
主体中的函数,因为
A
update\u例程
private
成员函数,因此我认为尝试从
B
调用它会导致
无法访问的方法
错误或者沿着这些线的东西-即使它已作为函数指针传递

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


附言:如果这是重复的,我很抱歉,如果是这种情况,请链接相关主题。

它是从a内部传递的,在a内部非常可见。可见性不会更改函数的类型。
如果您试图从
B::update\u quantity
调用
A::update\u例程
,这将是非法的。但是A已经将地址给了B,并将函数调用委托给了B。同时,B不知道它接收到什么函数地址。

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

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

术语public和private(和protected)实际上只指事物的名称——名称
update\u 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
类的引用。 您正在取消引用中的
fptr
更新\u数量
功能,但原型 对于
fptr
,没有对
A
类,因此不存在来自 B至A级

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

fptr
对于
update\u quantity
来说是严格本地的,不被认为是类的一部分

上述代码中没有对
A
类的引用。 您正在取消引用中的
fptr
更新\u数量
功能,但原型 对于
fptr
,没有对
A
类,因此不存在来自 B至A级

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


fptr
对于
update\u quantity
来说是严格本地的,不被认为是类的一部分。

B::update\u quantity如何尝试调用A::update\u例程?
A
可以访问自己的
update\u例程()
,所以能够提供有效的地址。当指针被传递到
B::update_quantity()
时,传递的唯一信息是它的地址和类型(一个具有指定参数/类型和返回值集的函数)。这不包括有关可访问性的信息-可访问性仅适用于其名称,而未提供该信息。B::update_quantity如何尝试调用A::update_例程?
A
可以访问其自己的
update_例程()
,因此能够提供有效地址。当指针被传递到
B::update_quantity()
时,传递的唯一信息是它的地址和类型(一个具有指定参数/类型和返回值集的函数)。这不包括有关可访问性的信息-可访问性仅适用于其名称,而不提供该信息。