在OOP中使用类C的API 我在C++中编写了一些班级,作为一个个人小图书馆,我遇到了一个问题。

在OOP中使用类C的API 我在C++中编写了一些班级,作为一个个人小图书馆,我遇到了一个问题。,c++,api,oop,design-patterns,singleton,C++,Api,Oop,Design Patterns,Singleton,我的一些对象让我们看到了用华丽的C风格编写的第三方库。 这意味着这些库具有类似于apinit()和apiCleanup()的函数,其中前者必须在任何实际api函数之前调用,后者必须在不再使用它们时调用 我想要的是为需要库的类提供其函数的访问点,确保在创建第一个需要的类时,或者至少在使用任何api函数之前调用apilinit(),并且在销毁最后一个使用api的实例时调用apilianup() 请记住,使用单个库的类不止一个 我可以提供两种解决方案: 首先,显而易见的一点是,将提供者设置为单例: #

我的一些对象让我们看到了用华丽的C风格编写的第三方库。 这意味着这些库具有类似于
apinit()
apiCleanup()
的函数,其中前者必须在任何实际api函数之前调用,后者必须在不再使用它们时调用

我想要的是为需要库的类提供其函数的访问点,确保在创建第一个需要的类时,或者至少在使用任何api函数之前调用
apilinit()
,并且在销毁最后一个使用api的实例时调用
apilianup()

请记住,使用单个库的类不止一个

我可以提供两种解决方案:

首先,显而易见的一点是,将提供者设置为单例:

#include <iostream>

using namespace std;


class ContextProvider {

  ContextProvider() {
    cout << "Initializing API" << endl;
  }

  ContextProvider(ContextProvider const& rhs) = delete;
  ContextProvider& operator=(ContextProvider const& rhs) = delete;

public:

  ~ContextProvider() {
    cout << "Cleaning API" << endl;
  }

  static ContextProvider& getInstance() {
    static ContextProvider instance;
    return instance;
  }

  void useContext() {
    cout << "Using API" << endl;
  }
};


class ContextUser1 {


public:

  ContextUser1() {

  }

  void doSomething() {
    ContextProvider::getInstance().useContext();
  }
};


class ContextUser2 {

public:

  ContextUser2() {

  }

  void doSomethingElse() {
    ContextProvider::getInstance().useContext();
  }
};
请给出预期结果,即:

初始化API
使用API
使用API
使用API
使用API
使用API
清洁原料药
现在明显的问题是,哪一个更好,或者我应该使用哪一个?

例如,我想到的一些事情是

单例法:

  • 优点:

    • 不需要存储任何计数器
    • 不需要存储任何实例
  • 缺点:

    • 语法变得奇怪(
      ContextProvider::getInstance().use()
    • 这是一个单身汉,有很多缺点
计数器方法:

  • 优点:

    • 用法是直截了当的
    • 合成很好且清晰(
      cp.use()
  • 缺点:

    • 必须保留一个用户数量计数器
    • 用户类必须存储ContextProvider类的实例
我问这个问题主要是因为我不知道这些优点/缺点中哪一个更重要,如果有我没有解释的事情,或者可能有第三种明显的方法我想不出来,它本质上比这两种更好,或者,谁知道呢


谢谢你抽出时间

我将使用您的第二种方法,并进行以下修改:

class ContextUser1 {
  std::shared_ptr<ContextProvider> cp;

public:

  ContextUser1(const std::shared_ptr<ContextProvider>& cp)
      : cp(cp) {
  }

  void doSomething() {
      cp->useContext();
  }
};
类上下文1{
std::共享的ptr cp;
公众:
上下文1(const std::shared_ptr&cp)
:cp(cp){
}
无效剂量测定法(){
cp->useContext();
}
};

使依赖项显式化可以使代码更好地进行测试。此外,使用
shared\u ptr
可以进行计数,因此您甚至不需要自己进行计数。

您可能正在寻找所谓的。这是标准库用来确保
std::cout
等在首次使用之前初始化并可用的技巧。重新启动API的成本有多高?API的对象多久会被销毁一次,然后很快创建新的对象?@IgorTandetnik这不是我在第二个示例中所做的吗?@rpattiso是的,我考虑过这个问题。我不知道它有多贵,但我正在考虑像GLFW或WinSock这样的API,所以这种情况不应该发生,或者至少是偶尔发生。也许更适合这种情况。
int main() {
  ContextUser1 cu11, cu12, cu13;
  ContextUser2 cu21, cu22;

  cu11.doSomething();
  cu12.doSomething();
  cu21.doSomethingElse();
  cu22.doSomethingElse();
  cu13.doSomething();
}
class ContextUser1 {
  std::shared_ptr<ContextProvider> cp;

public:

  ContextUser1(const std::shared_ptr<ContextProvider>& cp)
      : cp(cp) {
  }

  void doSomething() {
      cp->useContext();
  }
};