声明函数对象的全局实例的最佳方法是什么,以便我可以在整个程序中导入和使用实例作为callable?
具体来说,我创建了一个模板类,用作共享指针的自定义删除器。需要使用" Free"删除第三方库中的几种指针类型。引用指针的函数。该类的实例使用要删除的指针的类型进行实例化,并指向具有Free函数签名的函数的指针。我将实例声明为const,因为成员函数指针不需要更改。
template <class T>
class Deleter {
public:
typedef typename bool(CALLING_CONVENTION *DeleterFunc)(T**);
Deleter(DeleterFunc deleter) : deleter_(deleter) {}
void operator() (T* t) { if (t) { deleter_(&t) }
private:
DeleterFunc deleter_;
};
static const Deleter<I_x> x_deleter(FreeXInterface);
我的第一次尝试是.h文件中每个指针类型的创建实例,但如果我在其他代码中包含此头文件,则会产生多个定义的符号。所以我将实例的声明更改为&#34; static&#34;这编译似乎工作正常,但我已经看到警告,这不是一个好主意(特别是如果对象属于命名空间)因为静态导致链接只是文件,并且每个编译单元将有它自己的副本。
我的问题是,如果我真的不在乎它们是否是文件之间的相同实例,这是否重要?我没有将它用作全局数据,并且函数对象实际上没有任何状态。如果这些对象被声明为静态,我是否会担心线程?有没有更好的方法来实现它而不使用static关键字?
答案 0 :(得分:0)
嗯,你的链接器问题的基本答案在这里:How do I use extern to share variables between source files?让我们尝试做得更好一点:你每次实例化一个函数时,你当前必须引用删除函数,而不是它根据类型自动选择。
当然,我们经常根据类型选择 types :std::vector<int>
是能够保存int
的动态数组。链接在那里不是一个大问题:一切都或多或少内联,每个翻译单元提到std::vector<int>::push_back()
获取自己的目标代码副本以将int放入int的向量中,并且链接器(有时)帮助删除重复的实例化。但在这里我们想要一个对象,而不是一个类型。
那么模板和全局对象之间的中途是什么?模板类的静态成员!检查一下:
// Deleter.h
typedef typename bool(CALLING_CONVENTION *DeleterFunc)(T**);
template <class T>
class Deleter {
public:
static DeleterFunc s_deleterFunc;
void operator() (T* t) {
if(t) { s_deleterFunc(&t); }
}
};
// XDeleter.cpp
#include "Deleter.h"
template<>
DeleterFunc Deleter<I_x>::s_deleterFunc = FreeXInterface;
// YDeleter.cpp
#include "Deleter.h"
template<>
DeleterFunc Deleter<I_y>::s_deleterFunc = FreeYInterface;
对于您想要删除器的每种类型,您只需为专用类提供静态成员的实例化。调用Deleter<I_x>::operator()
的代码只需要包含Deleter.h
;链接器将负责将其与XDeleter.cpp
中声明的那个匹配。
请注意,我使用模板化的类而不是模板化的函数,只是因为它允许您使用函数指针。但你可以做一些简单的事情:
// Deleter.h
template <class T>
invokeDeleter(T* t);
// XDeleter.cpp
#include "Deleter.h"
template<>
invokeDeleter<I_x>(I_x* x)
{
...
}
// YDeleter.cpp
#include "Deleter.h"
template<>
invokeDeleter<I_y>(I_y* y)
{
...
}