症状:
在DLL中定义一个模板类并用__declspec(dllexport)定义。
- template<typename T, int d>
- class DLLExportExportMacro vectortemp
- {
- public:
- vector m_Vector;
- public:
- vectortemp(vector v):m_Vector(d)
- {
- if (v.size() == d)
- {m_Vector = v;}
- else
- throw invalid_argument("Vector size does not match.");
- }
- vectortemp(T v[]):m_Vector(d)
- {
- if (sizeof(v)/sizeof(T) == d)
- {
- vector::iterator iter = m_Vector.begin();
- int i = 0;
- while (iter != m_Vector.end())
- {
- *iter++ = v[i];
- }
- }
- else
- throw invalid_argument("Vector size does not match.");
- }
- vectortemp():m_Vector(d)
- {
- vector::iterator iter = m_Vector.begin();
- while (iter != m_Vector.end())
- {*iter = 0;}
-
- }
-
- const T &operator[](int index) const{return m_Vector[index];}
-
- T &operator[](int index){return m_Vector[index];}
- };
警告提示出现在line 6。意思说vector需要用dll接口(__declspec(dllimport))从而使其被客户类vectortemp使用。 __declspec(dllimport)用于所有需要从dll导入的对象,包括变量,函数,类等。而且必须用在定义前面。如果vectortemp中 使用的不是一个模板类vector<>,这里会报错。因为头文件vector里只是vector类的声明。在vector实例化时,编译器会 生成一份和头文件中一样的代码,一份本地类定义,当然加上模板参数,比如vector。所以用模板类不会出错,但编译器会友好地产生一个警告。警告不会影 响程序运行,可以不用理睬。但是随着使用vectortemp的增加,警告会越来越多。这个确实很丑陋!解决方法有两个:直接用下面这个命令关闭警告。
- #pragma warning( disable: 4251 )
第一个方法还是丑陋了点,而且也不能了解内幕。我们需要一个显示地实例化模板,从而得到模板的一个定义。对一个非stl模板,可以这样:
- template class DLLExportExportMacro SomeTemplate<int>;
- SomeTemplate<int> y;
对于stl模板,如果只是相应的改成
- template class DLLExportExportMacro std::vector<int>;
- std::vector<int> y;
你会得到这个:
- warning C4251: 'std::_Vector_val<_Ty,_Alloc>::_Alval' :
- class std::allocator<_Ty>' needs to have dll-interface to be \
- used by clients of class 'std::_Vector_val<_Ty,_Alloc>'
因为stl::vector的实际定义是"std::vector >"。所以还要import std::allocator。
- template class DLLExportExportMacro std::allocator<int>;
- template class DLLExportExportMacro std::vector<int>;
- std::allocator<int> >;
方法二:导致链接错误
如果同时有两个DLL库用用显示实例方法导出vector,会导致vector的重定义。唯一的解决办法就是用#pragma warning( disable: 4251屏蔽警告。
(scholfield) |