我正在使用一个现有的 C 库(我无法修改),其中某些结构具有不透明字段,必须通过特定的 setter 和 getter 访问这些字段,如下面的粗略示例所示(想象 x
是私有(private)的,即使它是用 C 编写的)。
struct CObject {
int x;
};
void setCObjectX(CObject* o, int x) {
o->x = x;
}
int getCObjectX(CObject* o) {
return o->x;
}
我正在编写私有(private)拥有这些类型结构的类,有点像包装器,尽管更复杂。我想以方便的方式公开相关领域。起初,我只是在必要的地方编写 setter 和 getter。不过,我想到了别的事情,我想知道这个方法是否有什么缺点。它使用函数指针 (std::function
) 来存储 C setter-getter 对,并将它们呈现为直接访问字段而不是函数。
这是我编写的通用类,用于帮助定义此类“假”字段:
template<typename T>
struct IndirectField {
void operator=(const T& value) {
setter(value);
}
auto operator()() const -> T {
return *this;
}
operator T() const {
return getter();
}
std::function<void(const T&)> setter;
std::function<T()> getter;
};
通过在C++类中定义实例并使用相应的C函数设置setter
和getter
来使用它:
IndirectField<int> x;
// ...
x.setter = [=](int x) {
setCObjectX(innerObject.get(), x);
};
x.getter = [=]() {
return getCObjectX(innerObject.get());
};
Here is a complete, working code for testing.
使用这种方法有什么缺点吗?它会导致最终的危险行为或其他什么吗?
最佳答案
我在您的解决方案中看到的最大问题是 std::function
对象在 CPPObject
内的 IndirectField
的每个实例中占用空间,甚至当CObject
类型相同时。
您可以通过将函数指针放入模板参数来解决此问题:
template<typename T,typename R,void setter(R*,T),T getter(R*)>
struct IndirectField {
IndirectField(R *obj) : obj(obj) {
}
void operator=(const T& value) {
setter(obj, value);
}
auto operator()() const -> T {
return *this;
}
operator T() const {
return getter(obj);
}
private:
R *obj;
};
以下是如何使用此实现:
class CPPObject {
std::unique_ptr<CObject,decltype(&freeCObject)> obj;
public:
CPPObject()
: obj(createCObject(), freeCObject)
, x(obj.get())
, y(obj.get()) {
}
IndirectField<int,CObject,setCObjectX,getCObjectX> x;
IndirectField<double,CObject,setCObjectY,getCObjectY> y;
};
此方法将每个 IndirectField
的两个 std::function
对象换成一个 CObject*
指针。不幸的是,需要存储此指针,因为您无法从模板内的上下文中获取它。
关于c++ - 公开不透明 C 结构体中的字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49172907/