1. 程式人生 > >如何解決VC中的警告Warning C4251

如何解決VC中的警告Warning C4251

這通常是由於以資料成員方式在DLL匯出類中使用了模板類造成的。比如:
#include <iostream>
#include <vector>
using namespace std;

class __declspec( dllexport ) Test
{
public:
std::vector<int> m_objCon;
};

int main()
{


return 0;
}

這會導致這個警告:
warning C4251: “Test::m_objCon”: class“std::vector<_Ty>”需要有 dll 介面由 class“Test”的客戶端使用
1>        with
1>        [
1>            _Ty=int
1>        ]
這個問題主要要描述的是不同的地方的vector的實現可能不一樣所造成的問題。所以我們應該將其匯出。有很多方法可以解決這個問題的。

第一種: 無視它或者#pragma warnind( disable: 4251 )
第二種:將該資料改為指標方式:
class __declspec( dllexport ) Test
{
public:
std::vector<int>* m_objCon;
};
然後在建構函式和解構函式中分別初始化和釋放它。
第三種:
將該模板類及其依賴類匯出。
#include <iostream>
#include <vector>
using namespace std;

class __declspec( dllexport ) Test
{
public:
template  class __declspec( dllexport ) std::allocator<int>;
template  class __declspec( dllexport ) std::vector<int, std::allocator<int> >;
public:

std::vector<int> m_objCon;
};

int main()
{


return 0;
}
這種方法要注意的是必須要把要匯出模板類的模板資料成員一併匯出。有點類似於顯式例項化。比如說你要匯出boost::shared_ptr就還必須將其依賴的shared_count一併匯出。匯出map還需要匯出對應pair等等。很麻煩啦~所以我們還是選擇第四種吧。

第四種:Impl。
#include <iostream>
#include <vector>
using namespace std;

// 這些放到.h中
class Test_imp;
class __declspec( dllexport ) Test
{
// 建構函式中初始化 析構中釋放m_pImp;
void test();
public:
Test_imp* m_pImp;
};

// 這個類放到cpp中去
class  Test_imp
{
public:
void test(){}
std::vector<int> m_objCon;
};

// 放到cpp中
void Test::test()
{
m_pImp->test();
}

int main()
{


return 0;
}

個人推薦第二種和第四種,反對第一種。畢竟掩耳盜鈴不是好習慣~~