【问题标题】:How to get offsetof() a private class-member?如何让 offsetof() 成为私有类成员?
【发布时间】: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 只是为您编写访问器函数的描述符的一个特例;它们通常不会更快(除非可能是由于使用共享热代码路径的意外)。

标签: python c++ python-3.x c++11 c++14


【解决方案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 内”,因此不算数。
猜你喜欢
  • 1970-01-01
  • 2011-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-22
  • 2014-09-22
  • 2019-12-29
相关资源
最近更新 更多