c++ - 公开不透明 C 结构体中的字段

标签 c++ c++11

我正在使用一个现有的 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函数设置settergetter来使用它:

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* 指针。不幸的是,需要存储此指针,因为您无法从模板内的上下文中获取它。

Your modified demo.

关于c++ - 公开不透明 C 结构体中的字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49172907/

相关文章:

C++ - std::function 作为仿函数的参数

c++ - 在 for-each 循环中使用 getter 是否效率低下?

c++ - 是否可以在 Objective-C++ 中删除 dispatch_once?

c++ - 如何在不创建实例的情况下获取std::array <T,N>中的元素数?

c++ - 成员函数引用限定返回类型

c++ - Windows CreateThread在类函数调用中,指针引用崩溃?

c++ - 当你有类层次结构时,方法的调用顺序是什么?

C++:getline() 是否读取了整行?

c++ - Arduino 数组中的损坏值

c++ - 在 C++ 中不能内联虚函数总是正确的吗?