在一個準備導出到其它應用中的類(Class)上使用
__declspec(dllimport)
指令時,會導緻虛函數表(vtables)駐留在所有執行個體化過該類的dll中。
如果任何一個執行個體化過該類的dll被解除安裝,所有在該dll中建立的執行個體都會失效。随後通路這些失效執行個體的虛函數時就會導緻記憶體錯誤。
是以,唯一安全地使用這個指令的辦法,就是強制要求任何執行個體化過該類的應用都不允許解除安裝。
為了確定這一要求,你必須要麼在文檔中明确說明,或者提供一個僞構造函數駐留在無法被解除安裝的dll中。
最好的方法就是避免使用這個指令。
唯一的例外就是如果這個類(Class)導出了一個靜态成員變量。
在這種情況下你應該隻在這個變量上使用
__declspec(dllimport)
,但是你應該避免把它應用到整個class。但是我們不推薦導出靜态成員變量。
本警告僅限于
__declspec(dllimport)
,它并不适用于
__declspec(dllexport)
.
建議的用法如下所示:
#pragma warning( disable: 4275 4251 )
#ifdef POLYSAMP
#define DLLIMPEXP __declspec( dllexport )
#else
#define DLLIMPEXP
#endif
// The "DLLIMPEXP" is only required for exporting a poly API or using
// the exported API. It is not necessary for any custom classes that
// are not exporting an API of their own.
//
class DLLIMPEXP AsdkPoly: public AcDbCurve
{
public:
ACRX_DECLARE_MEMBERS(AsdkPoly);
//*****************************************************************
// Constructors and destructor
//*****************************************************************
實際應用中,除非不使用該Class,否則無法隻對靜态成員變量使用
__declspec(dllimport)
附:
__declspec(dllimport)
的主要用法:
1. 在導入動态連結庫中的全局變量
2. 導出類的靜态成員
3.隐式使用dll時,在生成的二進制代碼上效率有所提高,可以節省一個跳轉指令。
MSDN裡的解釋:
不使用 __declspec(dllimport) 也能正确編譯代碼,但使用 __declspec(dllimport)
使編譯器可以生成更好的代碼。編譯器之是以能夠生成更好的代碼,是因為它可以确定函數是否存在于 DLL中,這使得編譯器可以生成跳過間接尋址級别的代碼,而這些代碼通常會出現在跨 DLL 邊界的函數調用中。但是,必須使用__declspec(dllimport) 才能導入 DLL 中使用的變量。
參考資料:
http://blog.csdn.net/mniwc/article/details/7993361
http://blog.csdn.net/Repeaterbin/article/details/4269666