我有一些代码和数据,它们当前都封装在一个结构中,而该结构又位于一个命名空间内。我正在尝试集成一个外部库,它使用老式的回调。我需要在回调上下文中访问我的数据,但回调 API 不提供添加个性化参数的方法。
我知道规避这个问题的唯一方法是向我的结构添加一个全局指针,以便回调知道在哪里找到数据,或者使用一堆 boost 类从我的结构创建一个假函数指针要使用的回调。这两个选项感觉更像是绕过 OOP 限制,而不是实际的解决方案。
因此,我正在争论是否完全放弃该结构,并将其转换为独立的代码和数据。本质上,数据将成为全局的(或更可能的是,包装在全局结构中),但将在其 namespace 的范围内。
使数据“全局化”的理由:
- 代码在程序中具有单一用途,并且在程序的生命周期中始终使用同一组数据。数据永远不会分配或释放。
- 此代码和数据从未被实例化。从来没有、也永远不会有多个拷贝。
- 我不喜欢 OOP(我使用 C++,因为它是完成这项工作的最佳工具),因此我认为没有必要仅在原则上对其进行封装。
但是,我想避免一个缺点:
- 即使数据位于单独的命名空间中(并且忽略我是唯一编写此程序的人这一事实),也没有什么可以阻止程序的其他部分访问此数据。如果真的发生了,我将没有简单的方法来追踪它。
到目前为止,我唯一的想法是将全局数据包装在未命名的命名空间中。出于所有意图和目的,这应该使其对代码库的其余部分不可见,并消除不使用全局变量的最常见原因。然而,这也意味着访问它所需的代码必须全部包含在一个文件中,如果该文件变大,这可能会变得很痛苦。
是否还有其他我没有想到的选择,或者这已经是最好的选择了吗?
最佳答案
您可以只使用一些模板化静态函数来为您提供数据指针,尽管您必须在编译时指定这些:
#include <iostream>
using namespace std;
template <class Data, int ID>
struct ext_library_context
{
static Data data;
static void callback()
{
// callback code, using data
cout << data << endl;
}
};
template <class Data, int ID>
Data ext_library_context<Data, ID>::data;
void ext_library_call(void callback())
{
callback();
}
int main()
{
int d1 = 1;
ext_library_context<int, 1>::data = d1;
int d2 = 2;
ext_library_context<int, 2>::data = d2;
ext_library_call(ext_library_context<int, 1>::callback);
ext_library_call(ext_library_context<int, 2>::callback);
}
只要您为每次调用使用唯一的数据/ID 模板参数组合,就不会有任何问题。
关于c++ - 从回调中访问数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7762506/