将 C 包装在 RAII 中而不公开类型

Wrapping C in RAII without exposing types

本文关键字:类型 包装 RAII      更新时间:2023-10-16

我正在尝试为某个c api编写一个包装器,特别是围绕一对采用以下形式的函数:

int add_list_a(ablist *l, int id);
int add_list_b(ablist *l, long id);

我想做的是隐藏这两者之间的区别,并有这样的东西:

class List
{
void addAB(AB *ab);
};
class AB {};
class A: public AB {int id;};
class B: public AB {long id;};

我宁愿不直接将指针直接放在公共接口中,因为这会使接口依赖于 boost::shared_ptr。(不能使用现代 c++(

然后我意识到很难定义不需要包装在智能指针中的类,并且没有公开一些内部结构来使其正常工作。

我可以做这样的事情:

class List
{ 
private:
ablist *l;
public:
void addAB(AB ab) {
ab.addToList(l);
}
};
class AB { 
private:
boost::shared_ptr<InternalAB> ab;
public:
void addToList(list *l) {
ab->addToList(l);
}
};
class InternalAB { virtual void addToList(list *l) = 0; }

内部使用这些类型:

class InternalA: public InternalAB {
public:
int id;
void addToList(list *l)
{
add_list_a(l, id);
}
};
class InternalB: public InternalAB {
public:
long id;
void addToList(list *l)
{
add_list_b(l, id);
}
};

但它非常复杂,并且仍然公开 addToList((。
A 和 B 是从静态函数创建的,所以它们的初始化不是问题,在我的情况下它们有很多通用代码,这就是为什么我想在它们之间保持一个通用类型。
有没有更好的方法可以做到这一点?我可能完全错过了一些东西,但这是一种特定的情况,我找不到类似的东西

以下是您的解决方案,尽可能接近您在示例中编写的内容:

class AB {
friend List;
protected:
virtual void addToList(ablist* list) = 0;
};
class A : private AB {
void addToList(ablist* list) override { add_list_a(list, id); }
int id;
};
class B : private AB {
void addToList(ablist* list) override { add_list_b(list, id); }
long id;
};
class List {
ablist* l;
public:
void add(AB* ab) {
ab->addToList(l);
}
};

唯一要调用的可访问函数是 List::add。 List 类包装 ablist 结构,类 A 和 B 基于示例中的类。