【发布时间】:2015-02-25 15:40:43
【问题描述】:
我正在尝试将 Python PyObject* 包装在 Object 类中。
在 Python 中,一切都是PyObject*。
一个列表是一个PyObject*,列表中的每个项目本身就是一个PyObject*。
这甚至可能是另一个列表。
等等
我正在尝试通过代理模式 (here) 来允许 fooList[42] = barObj 样式语法。
现在我已经完成了这项工作,我想扩展它,以便 fooList[42] 可以用作 Object。具体来说,我希望能够处理...
fooList[42].myObjMethod()
fooList[42].myObjMember = ...
Object有很多方法,目前fooList[42].myObjMethod()会先将fooList[42]解析成Proxy实例,比如tmpProxy,然后再尝试tmpProxy.myObjMethod()。
这意味着我必须这样做
void Proxy::myObjMethod(){ return wrapped_ob.myObjMethod(); }
即通过Proxy手动中继Object的每个方法,这很难看。
我看不到任何完美的解决方案(请参阅上面的链接答案),但我很乐意使用:
fooList[42]->myObjMethod()
... 作为一种折衷方案,看到 -> 可以重载(而 . 不能)。
但是,我找不到任何有关重载 operator-> 的文档。
我最好的猜测是它必须返回一个指向某个对象的指针(比如pObj),而C++ 将调用pObj->whatever。
以下是我尝试的实现。但是,我遇到了一个'获取 Object 类型的临时对象的地址'警告。
我有,在我的Object 类中:
const Object operator[] (const Object& key) const {
return Object{ PyObject_GetItem( p, key.p ) };
}
注意'const Object&'会遇到'获取Object类型的临时对象的地址'警告。
class Proxy {
private:
const Object& container;
const Object& key;
public:
// at this moment we don't know whether it is 'c[k] = x' or 'x = c[k]'
Proxy( const Object& c, const Object& k ) : container{c}, key{k}
{ }
// Rvalue
// e.g. cout << myList[5] hits 'const Object operator[]'
operator Object() const {
return container[key];
}
// Lvalue
// e.g. (something = ) myList[5] = foo
const Proxy& operator= (const Object& rhs_ob) {
PyObject_SetItem( container.p, key.p, rhs_ob.p );
return *this; // allow daisy-chaining a = b = c etc, that's why we return const Object&
}
const Object* operator->() const { return &container[key]; }
// ^ ERROR: taking the address of a temporary object of type Object
};
这个想法是允许myList[5]->someMemberObj = ... 样式语法。
myList[5] 解析为Proxy 实例,它包装了Object(myList 的第六个元素)。我们就叫它myItem吧。
现在我希望someProxy->fooFunc() 或someProxy->fooProperty 分别调用myItem.fooFunc() 或myItem.fooProperty。
我遇到了一个'获取 Object 类型的临时对象的地址'警告。
【问题讨论】:
-
要添加到 Jarod42 的答案中,我发现此表非常有用:en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B
-
我意识到我原来的标题与问题不符。因此我调整了标题,并针对原标题重新提出了适当的问题here
标签: c++ c++11 operator-overloading proxy-pattern