函数指针和访问——为什么这段代码是合法的?
Function Pointers and Access - Why is this code legal?
我最近遇到了一些让我很吃惊的事情,如果能得到一些澄清就好了。
假设我有一个 class 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);
}
//...
};
和一个class 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
主体中的函数,因为 A
的 update_routine
是 private
成员函数,因此我认为尝试从 B
调用它会导致 inaccessible method
错误或类似的错误 - 即使它已作为函数指针传递。
在我的项目中,当我执行上述操作时它编译并成功执行 - 这是为什么?当然,它确实 确实 编译和 运行 对我来说非常有用,但我想了解为什么会这样。
P.S: 很抱歉,如果重复,请link相关主题。
它是从A里面传过来的,那里比较显眼。可见性不会改变函数的类型。
如果您试图从 B::update_quantity
调用 A::update_routine
,这将是非法的。但是 A 已经把地址给了 B,并委托给它调用函数。同时 B 不知道它接收到什么函数地址。
public 和 private(和 protected)这两个词实际上只是指事物的名称——它是名称 update_routine
是私有的,只能解析为内部的实际函数class 的范围。因为你只使用class范围内的名称,所以没有问题。
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
class。
您正在取消引用 fptr
update_quantity
函数,但是原型
对于 fptr
没有任何引用
A
class-所以没有来自
class B 到 A.
update_routine
的地址可能作为
函数指针参数——但是 A 函数仍然没有像写的那样直接编码在 B 的 class 中。换句话说,如果函数指针只是一个参数,那么取消引用这个函数指针参数不一定会导致 class 特权冲突。
fptr
严格局限于 update_quantity
并且不被视为 A class..
的一部分
我最近遇到了一些让我很吃惊的事情,如果能得到一些澄清就好了。
假设我有一个 class 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);
}
//...
};
和一个class 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
主体中的函数,因为 A
的 update_routine
是 private
成员函数,因此我认为尝试从 B
调用它会导致 inaccessible method
错误或类似的错误 - 即使它已作为函数指针传递。
在我的项目中,当我执行上述操作时它编译并成功执行 - 这是为什么?当然,它确实 确实 编译和 运行 对我来说非常有用,但我想了解为什么会这样。
P.S: 很抱歉,如果重复,请link相关主题。
它是从A里面传过来的,那里比较显眼。可见性不会改变函数的类型。
如果您试图从 B::update_quantity
调用 A::update_routine
,这将是非法的。但是 A 已经把地址给了 B,并委托给它调用函数。同时 B 不知道它接收到什么函数地址。
public 和 private(和 protected)这两个词实际上只是指事物的名称——它是名称 update_routine
是私有的,只能解析为内部的实际函数class 的范围。因为你只使用class范围内的名称,所以没有问题。
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
class。
您正在取消引用 fptr
update_quantity
函数,但是原型
对于 fptr
没有任何引用
A
class-所以没有来自
class B 到 A.
update_routine
的地址可能作为
函数指针参数——但是 A 函数仍然没有像写的那样直接编码在 B 的 class 中。换句话说,如果函数指针只是一个参数,那么取消引用这个函数指针参数不一定会导致 class 特权冲突。
fptr
严格局限于 update_quantity
并且不被视为 A class..