在OOP中使用类C的API 我在C++中编写了一些班级,作为一个个人小图书馆,我遇到了一个问题。
我的一些对象让我们看到了用华丽的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() 请记住,使用单个库的类不止一个 我可以提供两种解决方案: 首先,显而易见的一点是,将提供者设置为单例: #
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();
}
};