0

我一直在为脚本语言开发一个包装库(部分是为了学习 c++11 功能,部分是为了满足特定需求)。出现的一个问题是将继承的对象导出到脚本语言。

问题涉及使用包装类的代理对象来调用函数。具体来说,如果一个函数采用Foo *,那么来自任何正在使用的脚本语言的对象代理都必须适当地转换。

有两种方法(我能想到的)来适当地为对象代理建模:

template <class T>
struct ObjectProxy {
   T *ptr;
};

或者:

struct WrappedClass {
  virtual ~WrappedClass() {}
};

struct ObjectProxy {
  WrappedClass *ptr;

  template <typename T>
  boost::shared_ptr<T> castAs() {
    return boost::dynamic_pointer_cast<T>(instance);
  }
};

第一个版本的问题是您需要提前知道ObjectProxy指向什么类型。不幸的是,对此没有简单的解决方案(请参阅我以前的许多问题)。经过一番调查,看起来大多数流行的库(例如 boost::python、LuaBind 等)都保留了所有类关系的图表,以便进行正确的转换。

第二种方法避免了所有这些,但确实添加了您包装的每个类都必须从 WrappedClass 继承的约束。

这是我的问题:任何人都可以用第二种方法想到任何主要问题,除了对用户来说有点烦人吗?即使您没有创建特定的类,您也应该始终能够对其进行子类化。例如,如果您有一些提供类的库Foo,那么您可以这样做:

class FooWrapped: public Foo, public WrappedClass {};

这确实使用户的事情变得不那么无缝(尽管我一直在研究自动化的方法),这确实意味着您可以依赖内置的 dynamic_cast 而不必编写自己的变体。

编辑

添加castAs()以使用例更清晰

4

1 回答 1

0

您的问题听起来像是boost::any旨在解决的问题。该解决方案基本上结合了您的两个想法:(未经测试的代码)

struct ObjectProxyBase {
  virtual ~ObjectProxyBase() {}
};

template <class T>
struct ObjectProxy : public ObjectProxyBase {
   T *ptr;
};

template <class T>
T *proxy_cast(ObjectProxyBase *obj) {
    auto ptr = dynamic_cast<ObjectProxy<T> *>(obj);
    if (!ptr)
        return nullptr;

    return ptr->ptr;
}
于 2013-01-10T06:04:39.193 回答