将 C 结构工厂函数与其相应的 C++ 包装类构造函数合并

Merging a C struct factory function with its corresponding C++ wrapping class constructor

本文关键字:C++ 包装类 合并 构造函数 结构 工厂 函数      更新时间:2023-10-16

考虑使用以下内容为 C 库编写一个 C++ 包装器(T是其他类型):

typedef struct { /*fields*/ } S;
S* alloc_S(const T*);
void free_S(S*);

我想编写一个从S继承class_S类,以便分别由于class_S::class_S(const T*)class_S::~class_S()而隐藏对alloc_Sfree_S的调用(消除了忘记调用free_S的风险)。

由于alloc_S已经为其返回的结构的所有字段分配和分配值,因此是否有一种优雅的方法来"围绕"该结构构建class_S对象的其余部分?

我的目标是避免类似的东西的开销(时间和空间)

class_S::class_S(const T* t)
{
    S* tmp = alloc_S(t);
    // deep-copy tmp into this
    free_S(tmp);
}

显然,与其从S继承,我可以编写class_S以拥有一个S*成员并使用它,但如果可能的话,我想避免这种方法。

这是一种非标准、令人困惑且无法维护的方法 - 请注意特殊的构造语法

#include <memory>

extern "C" {
    struct T {};
    struct S
    {
    };
    S* alloc_S(T*);
    void free_S(S*);
}

struct class_S : S
{
    void * operator new (std::size_t,  T* p)
    {
        return alloc_S(p);
    }
    void operator delete(void *p)
    {
        if (p) free_S(reinterpret_cast<S*>(p));
    }
};
int main()
{
    T t;
    auto ps = new (&t) class_S;

    delete ps;
}

总的来说,您可能最好使用带有自定义删除器的unique_ptr:

struct class_S
{
    struct deleter {
        void operator()(S*p) const noexcept {
            free_S(p);
        }
    };
    class_S(T* p) : impl_(alloc_S(p), deleter()) {}
    // add proxy methods as required
    std::unique_ptr<S, deleter> impl_;
};
int main()
{
    T t;
    auto mys = class_S(&t);
}