如何让 offsetof() 成为私有类成员?
Posted
技术标签:
【中文标题】如何让 offsetof() 成为私有类成员?【英文标题】:How to get offsetof() a private class-member? 【发布时间】:2018-09-05 19:10:39 【问题描述】:我有一个封装在 Python 类型中的 C++ 类 (Scenario
):
struct PyScenario
PyObject_HEAD
Scenario scen;
;
我想将Scenario
的一些私有成员公开给 Python 脚本——不使用显式的 getter/setter 函数:
static PyMemberDef scenarioMembers[]
(char *)"a",
T_DOUBLE, offsetof(PyScenario, scen._a),
"The a"
,
(char *)"b",
T_INT, offsetof(PyScenario, scen._b),
"The b"
,
NULL
;
不幸的是,当我编译上面的代码时,我收到一个错误,例如:'double Scenario::_a' is private within this context
。
我不想公开_a
和_b
,所以我尝试将PyMemberDef
声明为friend
的Scenario
:
class Scenario
#ifdef PY_MAJOR_VERSION
friend struct PyMemberDef;
#endif
private:
double _a;
int _b;
....
;
很遗憾,这并没有帮助...正确的方法是什么?
【问题讨论】:
“我想将 Scenario 的一些私有成员暴露给 Python 脚本——不使用显式的 getter/setter 函数:” - 为什么?为什么不想使用 getter 函数从对象中获取数据?这对我来说毫无意义。 @JesperJuhl:大概他们正试图利用PyMemberDef
为它们生成简单值的访问器的能力,而不是必须编写自定义函数以用于更复杂的/强大的PyGetSetDef
访问器方法。 CPython 大多是 C++ 盲的,所以它不能直接使用成员函数,这意味着他们必须编写包装器来调用成员函数。
谢谢你,@ShadowRanger。没错 - 我想要直接访问标准标量类型字段的速度和简单性,是的。
@MikhailT.:我会注意,虽然写GetSet
描述符与Member
相比显然更复杂,但在速度方面,它们应该大致相当; Member
s 只是为您编写访问器函数的描述符的一个特例;它们通常不会更快(除非可能是由于使用共享热代码路径的意外)。
【参考方案1】:
您所做的基本问题是(可能)全局变量的初始化程序位于全局上下文中。初始化器不是类的一部分,也不是函数的组件,所以它不能成为任何东西的朋友。
您应该将变量设为函数-static
变量。并且包含变量的函数可以是类的朋友。
PyMemberDef *PyMemberInitializers()
static PyMemberDef scenarioMembers[]
(char *)"a",
T_DOUBLE, offsetof(PyScenario, scen._a),
"The a"
,
(char *)"b",
T_INT, offsetof(PyScenario, scen._b),
"The b"
,
NULL
;
return scenarioMembers;
【讨论】:
好吧,这可能会奏效,但C++ manual 声称,从 C++11(我使用)开始,类型已经可以是“朋友”——不仅仅是函数/类.. . 我看错了吗? @MikhailT.:“类型已经可以是“朋友”——不仅仅是函数/类……”类是类型。不,您不能将int
声明为朋友。我的观点是,友谊和访问是关于访问成员的代码在哪里。大括号初始化列表中的代码不会获得访问类型成员的任何额外权限。函数内部的代码获得函数的访问权限。类定义中的代码获得类的访问权限。括号初始化列表中的代码具有该代码所在位置的访问权限,仅此而已。
那么,第四节here是什么意思?我想,通过将PyMemberDef
声明为朋友,我正在允许我正在尝试的用途......
@MikhailT.: friend T;
只是friend class/struct/union T;
的简写,正如该部分中明确指出的那样。我的意思是:如果X
是Y
的朋友,那意味着X
内的成员和定义可以访问Y
的私人信息。应用于X
类型对象的初始化程序不在“X
内”,因此不算数。以上是关于如何让 offsetof() 成为私有类成员?的主要内容,如果未能解决你的问题,请参考以下文章