接上一篇。shell
上一篇的dll在编译过程当中一直有一个警告warning C4251: ‘CLASS_TEST::m_structs’ : class ‘std::vector<_Ty>’ needs to have dll-interface to be used by clients of class ,百函数
度之才发现是由于DLL中导出了STL中的类,二STL中的类默认是没有导出的,所以报告这个警告。spa
程序中消除warning有两种方法:.net
消极一点不去理他,反正不是error;日志
积极一点,则想办法去掉。去掉又用两种方法:一种使用#pragma warning(disable: xxxx),眼不见,心不烦;另外就是找出解决问题的办法了。在头文件中,定义宏code
#ifdef DLL_EXPORT #define DLL_API __declspec(dllexport) #else #define DLL_API __declspec(dllimport) #endif
搜索之,获得解决办法,修改后代码以下:blog
class DLL_API dllBase { public: dllBase ( void ); ~dllBase ( void ); int get(); private: static int base; template class DLL_API allocator< string >; template class DLL_API vector<string, allocator< string > >; vector<string> m_list; };
但是这样编译又出问题了,error C2252: an explicit instantiation of a template can only occur at namespace scope。继续搜索之,说是应该吧上面的两句话放到类的外面接口
再次试之,成功了,代码以下ci
template class DLL_API allocator< string >; template class DLL_API vector<string, allocator< string > >; class DLL_API dllBase { public: dllBase ( void ); ~dllBase ( void ); int get(); private: static int base; vector<string> m_list; };
注:由于STL中只有vector能够直接导出,因此该方法成功了,如果将vector换成List,则依然会继续报告C4251错误,暂时还不知道怎么解决。get
虽然能够使用了,可是每次都在类前面写入那么一大堆东西,看着就有点烦,因而乎发现了一篇很是强大的日志,在其中发现了一个比较好的办法来解决这个问题,具体就不写了。
可是使用它定义的带参数的宏能够比较方便的修改。
代码以下:
#define DLL_STL_LIST( STL_API, STL_TYPE ) \ template class STL_API std::allocator< STL_TYPE >; \ template class STL_API std::vector<STL_TYPE, std::allocator< STL_TYPE > >; DLL_STL_LIST ( DLL_API, string ); class DLL_API dllBase { public: dllBase ( void ); ~dllBase ( void ); int get(); private: static int base; vector<string> m_list; };
参考的另外一篇博客:
1:状况一
若是类的定义里面仅含有 编译器内置的类型变量, int, float 等等. 或者成员函数仅使用了这些变量做为参数, 那么很简单.
直接
class __declspec(dllexport) YourClass
{
}
就好了.
2:状况二
若是类内部使用了别的类, 那么别的类最好也导出, 否则, 首先编译的时候会出现编译警告:
warning C4251: needs to have dll-interface
意思是,你使用另外的一些类型/接口, 可是这些类型或接口没有导出. 当你的client使用这些类型/接口的时候, 会出错!
class __declspec(dllexport) YourClass
{
YourAnatherClass m_data; // 这里会 出现 warning 4251. 若是YourAnatherClass 没有导出的话.
}
解决办法就是: 在YourAnatherClass定义的地方加上
class __declspec(dllexport) YourAnatherClass
{
}
如上, 当你的YourAnatherClass没有导出的时候, dll的使用方会出现连接错误
3:状况三
当类的内部使用了STL模板的时候, 也会出现C4251警告, 状况会有所不一样
class __declspec(dllexport) YourClass
{
vector m_data; // 这里会 出现 warning 4251. 由于vector类型没有被导出
}
上面的使用模板(不管是stl模板,仍是自定义模板)的代码,编译dll时会出现C4251警告, 可是dll的使用方, 却不会出现连接错误!!!
这个由于, dll的使用方那里也有一套模板的定义, 当他们使用那个vector的时候, 虽没有导出, 可是用户本身也有一套STL模板(或者是自定义的模板),用户会利用本身的模板实例化这个dll中没有导出的东西!
因此, 对于由于使用STL(或模板)出现的c4251警告, 关闭之便可
#pragma warning(push)
#pragma warning(disable:4251)
//your declarations that cause 4251
#pragma warning(pop)
若想不使用经过关闭警告的方式关闭警告, 那么就这样
1)对于用户自定义的模板
template class DLLImportExportMacro SomeTemplate;
SomeTemplate y;
2)对于STL的模板
template class DLL_API allocator< string >;
template class DLL_API vector<string, allocator< string > >;
vector<string> m_data;