我有一些代码和数据,它们当前都封装在一个结构中,而结构又位于一个名称空间内。我正在尝试集成一个外部库,它利用了老式的回调。我需要在回调的上下文中访问我的数据,但回调API没有提供添加个性化参数的方法。
我知道绕过这个的唯一方法是添加一个指向我的struct的全局指针,以便回调知道在哪里找到数据,或者使用一堆boost类来从我的struct中创建一个假的函数指针回调使用。对于OOP限制而言,这两种选择更像是实际解决方案。
所以,我正在讨论是否完全抛弃结构,并将其转换为独立的代码和数据。从本质上讲,数据将变为全局(或者更有可能,包含在全局结构中),但它将在其命名空间的范围内。
使数据“全球化”的理由:
但是,我希望避免一个缺点:
到目前为止,我唯一的想法就是将全局数据包装在一个未命名的命名空间中。对于所有意图和目的,这应该使其对代码库的其余部分不可见,并消除不使用全局变量的最常见原因。但是,这也意味着 需要访问它的代码必须全部包含在一个文件中,如果该文件变大,这可能会变得很麻烦。
还有其他选择我没有考虑过,或者这是不是很好?
答案 0 :(得分:2)
您可以使用一些模板化的静态函数来为您提供数据指针,但您必须在编译时指定它们:
#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模板参数组合,就不会有任何问题。
答案 1 :(得分:1)
至于保护您的全局状态不被意外使用,您可以将其包装在一个类中,将成员标记为私有品尝,并将回调函数声明为朋友。
答案 2 :(得分:0)
将您的数据放入一个类并实例化此类 static -ally:
class MyClass {
private:
Data data; // variables which you avoid declaring globally
public:
void real_callback() {
do_something(data);
}
};
void callback() {
static MyClass my_class; // here is the trick.
my_class.real_callback();
// Or you can instantiate it on heap
// static auto my_class = new MyClass;
// my_class->real_callback();
}
int main() {
old_function_wanting_a_callback(callback);
}