如何让 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 声明为friendScenario

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 相比显然更复杂,但在速度方面,它们应该大致相当; Members 只是为您编写访问器函数的描述符的一个特例;它们通常不会更快(除非可能是由于使用共享热代码路径的意外)。 【参考方案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; 的简写,正如该部分中明确指出的那样。我的意思是:如果XY 的朋友,那意味着X 内的成员和定义可以访问Y 的私人信息。应用于X 类型对象的初始化程序不在“X 内”,因此不算数。

以上是关于如何让 offsetof() 成为私有类成员?的主要内容,如果未能解决你的问题,请参考以下文章

让公共成员变量访问 C++ 中同一类的私有成员

❥关于C++之私有继承

为啥 PRIVATE 成员函数不能成为另一个类的友元函数?

js里面如何才能让成员方法去调用类中其他成员

我怎样才能访问派生类私有方法?

作为 B 类成员的 A 类如何共享 B 类的私有成员?