在RAII中包装C而不暴露类型

时间:2017-07-12 13:00:51

标签: c++ raii c++98

我试图为某个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是从静态函数创建的,所以它们的初始化不是问题,在我的情况下它们有很多共同的代码,这就是为什么我想在它们之间保持一个共同的类型。
有一个更好的方法吗 ?我可能完全错过了一些东西,但这是一个特定的案例,我找不到类似的东西

1 个答案:

答案 0 :(得分:0)

这是您的解决方案尽可能接近您在示例中所写的内容:

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基于你的例子中的类。