资源代理类... C ++最佳实践

时间:2018-06-17 09:31:38

标签: c++ value-class

我有一个常见的问题就是为C库编写一个C ++包装器...我的主存储器是一个C-Struct指针,它们总是代表一个只包含 ONE 数据字段的C ++类。

class MyClassC {
  struct MyStructS * hdl
  ...
}

创建所有构造函数,静态和方法函数是没有问题...我的设计问题现在是......我应该使用类设计还是指针类设计。

value 类总是返回对象, NOT 指针:

类在 MyStructS MyClassC ONE 到 MANY 的关系>

MyClassC myMethod () {
  ...
  return MyClassC(struct MyStructS *...);
}

类的析构函数从不免费 struct MyStructS指针,并且大部分为空

的析构函数是静态方法,主要称为 destry delete

MyClassC::delete() {
   DestroyMyPointer(&hdl)
}
...
MyClassC obj = {...};
...
obj.delete();
...

value 类也是方法 value 的参数:

some_proc_or_method (MyClassC arg1, MyClassC arg2, …) {
   ...
} 

还有一个问题:

  

如何为类参数创建默认参数?

some_proc_or_method (MyClassC arg1, MyClassC arg2 = MyClassC {...} ???? ) {
   ...
} 

指针类总是返回对象的指针:

指针类在 MyStructS MyClassC ONE 到 ONE 关系>

MyClassC* myMethod () {
  ...
  return this or getThisFrom(myStructS_pointer)
}

指针类的析构函数总是免费 struct MyStructS指针

~MqClassC () {
   DestroyMyPointer(&hdl)
 }

...
MyClassC* obj = new MyClassC(...);
...
delete obj;
...

1 个答案:

答案 0 :(得分:0)

我选择选项3:一个薄的包装器,首先获得所有权。 C代码在C ++中已经很有用了。获得包装它的唯一实际好处是获得所有权语义正确。您的两种方法都试图将所有权跟踪到您的API用户身上。这不是一个有用的包装器,它只是添加了一个多余的间接层。您的客户仍需要注意C API的内部有效。

我建议的是你返回一个具有明确所有权语义的智能指针。编写一堆内联自由函数,接受智能指针并转发到C API。最终结果是,您具有几乎相同的API(较少的学习曲线),具有C ++所有权语义。这是一个收获,结果将不那么繁琐。

#include <memory>
#include <CLibAPI.h>

namespace CPPWrapC {
  namespace detail {
    struct DestroyMyPointer {
      void operator()(MyStructS *hdl) {
        ::DestroyMyPointer(&hdl);
      }
    };
  }

  using Handle = std::unique_ptr<MyStructS, detail::DestroyMyPointer>; 


  Handle myMethod() {
    MyStructS *ret = /* init it */;
    return Handle{ret};
  }

  inline void some_proc_or_method(Handle const& hdl) {
    c_lib_some_proc_or_method(hdl.get());
  }
}

所以现在你有一个简单的包装器,支持具有单一所有权语义的句柄。我想你到底想要什么。使用它几乎就像使用原始包装的API一样,因此客户可以充分利用他们对C库的了解。

这可以作为踏脚石。现在你有了一个C ++类型,你可以将其作为成员包含在内,以便进一步包装。