編譯時提示error C2065: 「IDD_DIALOG1」 : 未聲明的標識符html
錯誤的可能緣由及解決方法以下:
1.出錯文件中沒有包含資源文件ID聲明的resource.h文件。在出錯文件中加入#include 「resource.h」語句。ios
2.工程附件包含目錄的路徑下沒有resource.h文件。修改路徑便可。c++
3.工程所在文件夾下存在resource.h文件,但其中沒有資源ID的定義, 致使真正的resource.h沒有包含進去,刪除之。一個解決方案裏面有多個工程,可能會把全部資源ID的聲明放到一個文件中。在各個工程中實現對話框 功能的文件中,只需包含該文件便可。可是,當新增某個資源之後,工程中會自動生成一個resource.h(不知道爲何會這樣),而不是在已有的 resource.h文件中添加ID的定義。因爲工程編譯的時候先從本地搜索頭文件,會包含了自動生成的頭文件,因而出現了上述錯誤。程序員
注意:若是是智能設備程序出現此錯誤,應該確保resourceppc.h和Resourceppc.h中都有相同的宏定義#define IDD_DIALOG1 XXX,而且在dialog.cpp中包含資源頭文件resourceppc.h面試
==============================================================
redis
二、error C2471: 沒法更新程序數據庫 ,fatal error C1083: 沒法打開程序數據庫文件數據庫
fatal error C1083: 沒法打開程序數據庫文件:「c:documents and settings........debugvc90.pdb」: No such file or directory ....編程
解決方法:windows
修改一下設置,就能夠解決C2471:
CC++ | General | Debug Information format | C7 Compatible (/Z7)
CC++ | Code Generation | Enable String Pooling | Yes (/GF)
Linker | General Debug Info | Yes (/DEBUG)app
或者把在debug文件夾下的.pdb文件給刪除了,f5一下就好了
================================================================
三、error沒法打開預編譯頭文件的解決方法及預編譯頭原理
1。用VC.NET編輯程序,按Ctrl+F7,出現下列錯誤:
fatal error C1083: 沒法打開預編譯頭文件:「Debug/UGFace.pch」: No such file or directory
解決方法:修改:項目->屬性->C/C++ ->預編譯頭->不使用預編譯頭 便可。
2。學用Visual C++ 6.0的第一個例程就讓我出了錯.用嚮導生成第一個基於對話框的Project以後,當我按照書上的源程序一個字一個字地輸進去以後,始終有一個錯誤:
fatal error C1010: unexpected end of file while looking for precompiled header directive.找了無數次以後,我決定把嚮導生成的包括頭文件的語句:include"StdAfx.h"保留(而這以前我是把它刪掉了的,由於書 上的例子沒有這句.)咦,這下就對了.這是爲何呢?我百思不得其解。
來 到個人VC源代碼目錄,我注意到每一個Project下面的DEBUG文件夾都特別大,並且一個擴展名爲 .pch的文件佔去了絕大部分,我刪掉之好像對程序編譯運行沒有什麼影響。因而抱着對.pch文件的好奇,我在網上搜到了我疑惑之處的解答。這就是 VC++6.0給咱們帶來的:預編譯頭文件。預編譯頭文件(通常擴展名爲.PCH),是把一個工程中較穩定的代碼預先編譯好放在一個文件(.PCH)裏。 這些預先編譯好的代碼能夠是任何的C/C++代碼,甚至能夠是inline函數,只是它們在整個工程中是較爲穩定的,即在工程開發過程當中不會常常被修改的 代碼。
爲何須要預編譯頭文件?
一 言以蔽之:提升編譯速度.通常地,編譯器以文件爲單位編譯。若是修改了一工程中的一個文件則全部文件都要從新編譯,包括頭文件裏的全部東西 (eg.Macro宏,Preprocessor預處理),而VC程序中,這些頭文件中所包括的東西每每是很是大的,編譯之將佔很長的時間。但它們又不常 被修改,是較穩定的,爲單獨的一個小文件而從新編譯整個工程的全部文件致使編譯效率降低,所以引入了.PCH文件。
如何使用預編譯頭文件以提升編譯速度?
要 使用預編譯頭文件,必須指定一個頭文件(.H),它包含咱們不會常常修改的代碼和其餘的頭文件,而後用這個頭文件來生成一個預編譯頭文件 (.PCH),VC默認的頭文件就是StdAfx.h,由於頭文件是不能編譯的,因此咱們還須要一個.CPP文件來做橋樑,VC默認的文件爲 StdAfx.cpp,這個文件裏只有一句代碼就是:#include "StdAfx.h"。接下來要用它生成.PCH文件,涉及到幾個重要的預編譯指令:/Yu,/Yc,/Yx,/Fp。簡單地說,/Yc是用來生 成.PCH文件的編譯開關。在Project->setting->C/C++的Category裏的Precompiled Header,而後在左邊的樹形視圖中選擇用來編譯生成.PCH文件的.CPP文件(默認即StdAfx.cpp),你 就能夠看到/Yc這個開關,它表示這個文件編譯了之後是否生成.PCH文件(可能/Yc的c表示create)。/Fp指令指定生成的.PCH文件的名字 及路徑(可能/Fp的p表明path)。/Yu的u即use,工程中只要包括了.H文件的文件都會有這個/Yu指令。若是選擇自動 Automatic...的話則原來爲/Yc的地方就換成了/Yx指令。若是選擇自動,則每次編譯時編譯器會看之前有沒有生成過.PCH文件,有則不現生 成不然就再次編譯產生.PCH文件。
注意:
A, 實際上,由Appzard項目嚮導生成的默認的頭文件及CPP文件StdAfx.h和StdAfx.cpp能夠是任何名字的.緣由很簡單。但若是你要這樣 作就要記得修改相應的Project->setting...下的幾個預編譯指(/Yc,/Yu,/Yx,/Fp)的參數。
B. 在任何一個包括了將要預編譯的頭文件而使用了.PCH文件的工程文件的開頭,必定必需要是在最開頭,你要包含那個指定生成.PCH文件的.H文件(通 過.CPP文件包括,默認爲StdAfx.cpp),若是沒包括將產生我最開頭產生的錯誤.若是不是在最開頭包括將產生讓你意想不到的莫名其妙錯誤,如若 不信,盍爲試之?
C.預編譯文件.PCH生成之很耗時間,並且生成以後它也很佔磁盤空間,常在5-6M,注意項目完成以後及時清理無用的.PCH文件以節約磁盤空間。
D.若是丟了或刪了.PCH文件而之後要再修改工程文件時,可將指定的/Yc的.CPP文件(默認爲StdAfx.cpp)從新編譯一次便可再次生成.PCH文件,不用傻傻的按F7或Rebuild All
以 前還碰到過另一種狀況:新建一個工程,隨便找一個cpp文件,按ctrl+f7系統將會提示:fatal error C1083: 沒法打開預編譯的頭文件:」Debug/xxx.pch」: No such file or directory(其中xxx是工程的名字)這種狀況也是同樣的緣由,爲vc的stdafx.h頭文件未編譯所致。也能夠這樣解決:先F7,編譯後再 ctrf+f7。
vc2005error:沒法執行添加/移除操做,由於代碼元素是隻讀的
出現這種現象,多數是由於你的工程所在文件夾的屬性設置爲了「只讀」,你能夠關閉解決方案,而後從新打開,就能夠了,若是之後不想出現這樣的狀況,把工程所在的文件夾屬性中的「只讀」去掉,就能夠了。
解決方案:
一、重啓VS2005
二、查看.h和.cpp文件的屬性,有多是隻讀的,修改屬性後就能夠了
三、打開Resource.h文件看看 一看就知道了 有些定義重複了 能夠手動改掉 保存 編輯器從新加載
四、把你要添加事件的對話框相應的類文件(*.h和*.cpp)給關了就能夠了
五、關閉解決方案,刪除.ncb文件從新添加便可
六、實在不行就手動添加消息處理
在BEGIN_MESSAGE_MAP(。。。)
//這裏要刪掉你原先已經增長過的消息隱射函數
END_MESSAGE_MAP()
================================================================
五、程序運行出現-1.#IND,1.#INF
INF就是infinite,就是無窮大的意思
IND可能表示很小,不肯定
//////////////////////////////////////////////////////////
使用相似於pow, exp等等函數時常會產生一個無效數字1.#IND00,在VC下能夠經過與一個肯定數字比較大小來判斷是否產生了無效數字,但這個方法在DEV-CPP下倒是行不通的。
其實解決辦法很簡單,使用 float.h中一個函數_isnan便可:
int _isnan(double x);
當x是一個無效值(NaN, Not a Number) 時,返回非零值
不然返回0
================================================================
六、LINK : 上一個增量連接沒有生成它;正在執行徹底連接
代碼
#include"iostream"
using namespace std;
int main()
{
cout<<"123";
return 0;
}
LINK : 沒有找到 D:Visual Studio 2008ProjectstestDebugtest.exe 或上一個增量連接沒有生成它;正在執行徹底連接
在對話框中類中添加對CListCtrl控件右鍵處理的時候出現以下錯誤:
error C2440: 'reinterpret_cast' : cannot convert from 'NMHDR *' to 'NMITEMACTIVATE' Conversion requires a constructor or user-defined-conversion operator, which can't be used by const_cast or reinterpret_cast
須要把:LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<NMITEMACTIVATE>(pNMHDR);
; 改成: LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<NMITEMACTIVATE*>(pNMHDR);
參考:http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=339678
================================================================
八、沒法解析的外部符號 _WinMain,該符號在函數 ___tmainCRTStartup 中被引用
一,問題描述
MSVCRTD.lib(crtexew.obj) : error LNK2019: 沒法解析的外部符號_WinMain@16,該符號在函數 ___tmainCRTStartup 中被引用
Debugjk.exe : fatal error LNK1120: 1 個沒法解析的外部命令
error LNK2001: unresolved external symbol_WinMain@16
debug/main.exe:fatal error LNK 1120:1 unresolved externals
error executing link.exe;
二,產生這個問題可能的緣由
產生這個問題的真正緣由是c語言運行時找不到適當的程序入口函數,通常狀況下,若是是windows程序,那麼WinMain是入口函數,若是是dos控制檯程序,那麼main是入口函數,而若是入口函數指定不當,很顯然c語言運行時找不到配合函數,它就會報告錯誤。
可能:
1, 你用vc建了一個控制檯程序,它的入口函數應該是main, 而你使用了WinMain.
2. 你用vc打開了一個.c/.cpp 文件,而後直接編譯這個文件,這個文件中使用了WinMian而不是main做爲入口函數。vc這時的默認設置是針對控制檯程序的。
3.根本就沒有WinMain或Main函數。
三, 解決方法
1.進入project->setting->c/c++, 在category中選擇preprocessor,在processor definitions中刪除_CONSOLE, 添加_WINDOWS
2.進入project->setting->Link, 在Project options中將 /subsystem:console改成/subsystem:windows.
3.保存設置,Rebuild All.
四,VS2008中的設置
1.菜單中選擇 Project->Properties, 彈出Property Pages窗口
2.在左邊欄中依次選擇:Configuration Properties->C/C++->Preprocessor,而後在右邊欄的Preprocessor Definitions對應的項中刪除_CONSOLE, 添加_WINDOWS.
3.在左邊欄中依次選擇:Configuration Properties->Linker->System,而後在右邊欄的SubSystem對應的項改成Windows(/SUBSYSTEM:WINDOWS)
4.Rebuild All. Ok ?
================================================================
九、fatal error LNK1112: 模塊計算機類型「ARM」與目標計算機類型「X86」衝突
fatal error LNK1112: 模塊計算機類型「ARM」與目標計算機類型「X86」衝突
解決方法:連接器 -> 命令行 -> 附加選項, 添加 /MACHINE:ARM /MACHINE:THUMB
fatal error LNK1112: 模塊計算機類型「THUMB」與目標計算機類型「ARM」衝突
解決方法:
第1種:連接器 -> 命令行 -> 附加選項, 添加 /MACHINE:THUMB
第2種:新建項目時,在"平臺"->"選擇要添加到當前項目中的 Platform SDK。"中,把"已安裝的 SDK"所有添加到"選定的 SDK"
若是是直接使用已經建立好的工程,那麼第一種方法就能夠解決了,實在不行,就只有採用第二種辦法從頭解決了 。
================================================================
十、error c3872: 「0x3000」: 此字符不容許在標識符中使用
例如friend ostream& operator<<(ostream& out,const Chain<T>& x );
出錯error c3872: 「0x3000」: 此字符不容許在標識符中使用
解決方法:
0x3000是漢語的空格,也就是全角空格,至關於一個漢字,但你又看不見它。
像逗號,有半角(,)和全角(,)之分的,其實空格也有。
0x3000是全角的空格,0x20是半角的空格。
你最好把這個語句的後面空白部分都刪除掉,並檢查是否有中文標點存在。
================================================================
十一、0x????處未處理的異常:0xC0000005
使用VC編碼的時候常常會出現「Test.exe 中的 0x00414030 處未處理的異常: 0xC0000005: 寫入位置 0xfeeefeee 時發生訪問衝突 。」
出現0xC0000005的緣由通常都是沒有分配內存 或者 內存無效 所致,
例如:
#include "stdafx.h"
#include <string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
string * s = NULL;
s = new string();
delete s;
if (s != NULL)
{
*s = "TEST"; //這步操做將引發異常。
}
return 0;
}
雖然s已經被delete了,可是s的值並不爲NULL,if語句的判斷將失效,這是新手常見的一個錯誤!
爲了防止這個錯誤能夠本身定義一個宏來處理delete。
#define _DELETE(obj) if (obj != NULL) {delete obj , obj = NULL;}
使用這個宏能夠防止相似錯誤出現。
================================================================
十二、沒有找到MFC80UD.DLL,所以這個程序未能啓動.從新安裝應用程序可能會修復此問題
在vs2005 sp1中文版中,在「解決方案資源管理器」中的項目上右擊,選擇「屬性」,找到「配置屬性」中的「連接器」,而後找到「清單文件」,在右邊的屬性框中,默認「生成清單」項爲「是」,選 把「是」改爲「否」,運行之,出錯,而後再把否改回來,OK。
其餘:
(1)若是不選"系統菜單"和"關於菜單"就不會有這個問題!
(2)若是在"工程屬性->配置屬性->常規->字符集"選"使用多字節字符集"也不會出這個問題!
(3)好像是刪除全部的中間文件,(具體一點說,就是刪除."(工程文件)"Debug裏的文件和.ncb),再"從新生成解決方案文件...",可能能夠.
(4)clean關閉vs,打開rebuild應該就能夠了,個人不多遇到。遇到以後這樣就解決了。不行就多試幾回。
(5)linker-》manifest-file-》Generate Manifest: Yes
(6)Manifest搞的鬼,而後修改項目屬性,清單工具中的輸入輸出把嵌入清單文件選否.而後編譯,連接運行,成功
debug---動態使用dll
release---靜態使用dll
debug狀態下使用,會時不時出這個問題;
release狀態下使用,不會出現這個問題。
================================================================
1三、沒有找到MFC80D.DLL或msvcr80d.dll的解決方法
解決方案:
在編輯狀態下,點項目菜單 -> XXX屬性頁 -> 配置屬性 -> 清單工具,將右面的「使用FAT32解決辦法」選爲「是」便可。簡單地,其實把程序目錄下的Debug目錄整個刪掉,再讓VS所有從新生成文件也能解決這個問題,只是可能再犯。
沒有找到MFC80D.DLL的解決方法。問題出如今程 序運行清單上,默認是"嵌入清單",清單文件是"$(IntDir$(TargetFileName).embed.manifest"。調試程序運行 時,不知道爲何卻定位不到這個文件,咱們若是手動把"程序名.embed.manifest"改成"程序名.manifest",調試程序便可定位到。
其餘
方法一:
在C:Program FilesMicrosoft Visual Studio 8VCredi
stDebug_NonRedistx86Microsoft.VC80.DebugCRT 下找到了下列文件:
msvcm80d.dll
msvcp80d.dll
msvcr80d.dll
Microsoft.VC80.DebugCRT.manifest
把這幾個文件拷貝到目標機器上,與運行程序同一文件夾或放到system32下,就能夠運行那個程序了。
方法二:
修改編譯選項,將/MD或/MDd 改成 /MT或/MTd,這樣就實現了對VC運行時庫的靜態連接,在運行時就再也不須要VC的dll了。
================================================================
1四、fatal error LNK1181: 沒法打開輸入文件「..filename.lib」
================================================================
1五、沒有找到MFC80D.DLL,所以這個程序未能啓動.從新安裝應用程序可能會修復此問題
解決方法:刪除程序目錄下Debug文件夾和Release文件夾,而後從新編譯執行。
===網上其餘方法=============
方法一:
沒 有找到MFC80D.DLL的解決方法。問題出如今程序運行清單上,默認是"嵌入清單",清單文件是 "$(IntDir$(TargetFileName).embed.manifest"。調試程序運行時,不知道爲何卻定位不到這個文件,咱們若是 手動把"程序名.embed.manifest"改成"程序名.manifest",調試程序便可定位到。
方法二:
在C:Program FilesMicrosoft Visual Studio 8VCredistDebug_NonRedistx86Microsoft.VC80.DebugCRT 下找到了下列文件:
msvcm80d.dll
msvcp80d.dll
msvcr80d.dll
Microsoft.VC80.DebugCRT.manifest
把這幾個文件拷貝到目標機器上,與運行程序同一文件夾或放到system32下,就能夠運行那個程序了。
方法三:
修改編譯選項,將/MD或/MDd 改成 /MT或/MTd,這樣就實現了對VC運行時庫的靜態連接,在運行時就再也不須要VC的dll了。
================================================================
1六、mspdb80.dll沒法找到的解決方法
在cmd中鍵入cl執行編譯時會出現mspdb80.dll沒法找到的狀況,是由於VCBin下沒有「msobj80.dll,mspdb80.dll,mspdbcore.dll,mspdbsrv.exe」這四個文件,解決的方法:
1>直接從Microsoft Visual Studio 8Common7IDE下複製這四個文件到Microsoft Visual Studio 8VCBin下便可解決
2> 添加系統變量(Path),這樣:個人電腦->屬性->高級->環境變量->系統變量,在path中添加C:Program FilesMicrosoft Visual Studio 8Common7IDE;,注意結尾最後用「;」隔開!
這樣在用cl編譯就不會出現mspdb80.dll文件找不到的錯誤了。
================================================================
1七、error LNK2019: 沒法解析的外部符號....該符號在函數 ...中被引用
這種狀況通常都是函數只找到聲明但沒有實現,或者是少了什麼連接庫,你能夠試試把那兩個.h和.c文件直接加入工程中再試試。
有一個解決方案,有兩個工程A,B。工程B中定義了一個類,在工程A的demo.cpp中引用該類,可是若是是
#include "XX,h",則會出現「error LNK2019: 沒法解析的外部符號」
若是是#include "XX.cpp",則能夠順利編譯經過。
想來是由於引用 .h 文件致使找不到.cpp中的定義,而引用.cpp能夠經過.cpp找到.h(.cpp有對.h的include)
可是若是同在工程B下面,則#include "XX,h"也是正確的,它會自動關聯到同名的(反正是對應的).cpp文件。
在不一樣工程中應該如何引用呢?
看見一種緣由分析,以下:
現場狀況:
funcname 在文件file.cpp/h中定義實現
void funcname(void) {;}
filecall.c文件內呼叫funcname()函數。
出現上面狀況。
症因:因c/c++混合編程, c文件內函數沒法呼叫c++文件內函數。
解決,或者將c文件名改成.cpp,或者將c++文件名改成.c
上面的解決採用將 file.cpp 改名爲file.c便可。
1.
在 Visual C++ .NET 2003 中,若是使用了 /clr 而未將 CRT 連接到可執行文件,將生成此錯誤。任何由編譯器在未使用 /clr:initialAppDomain 時生成的對象代碼都包含對 _check_commonlanguageruntime_version 函數的引用,該函數在 C 運行時庫 (CRT) 中定義。若是應用程序在運行庫的版本 1 上運行,該函數將會生成一個錯誤信息。當前編譯器生成的代碼與運行庫的版本 1 不兼容。所以,若是在 Visual C++ .NET 2003 中編譯時不使用 CRT,則應在代碼中包含 _check_commonlanguageruntime_version 函數的定義。做爲使用 _check_commonlanguageruntime_version 函數的替代方法,您能夠與 nochkclr.obj 連接。nochkclr.obj 包含該函數的一個空版本,當您在運行庫的版本 1 上運行應用程序時,nochkclr.obj 不生成錯誤信息。若要使用當前編譯器版本生成應用程序以在運行庫的之前版本上運行,應使用 /clr:InitialAppDomain。
若要 生成一個純 MSIL 可執行文件(不與 CRT 連接),則必須在項目中定義該函數,而不能使用 nochkclr.obj(.obj 是本機代碼)。有關可驗證代碼的更多信息,請參見產生可驗證的 C++ 託管擴展組件。有關從託管 C++ 項目建立純 MSIL 輸出文件的更多信息,請參見將 C++ 託管擴展項目從混合模式轉換成純 IL。
2.
請看下面的示例:
extern int i;
extern void g();
void f()
{
i++;
g();
}
int main()
{
}
若是在生成中包含的某個文件中沒有定義 i 和 g,連接器將生成 LNK2019。能夠添加這些定義,方法是將包含這些定義的源代碼文件包括爲編譯的一部分。或者能夠將包含這些定義的 .obj 或 .lib 文件傳遞給連接器。
3.
對於從早期版本升級到當前版本的 C++ 項目,若是定義了 __UNICODE 而且入口點爲 WinMain,須要將入口點函數的名稱更改成 _tWinMain 或 _tmain。
4.
符號聲明包含拼寫錯誤,以至於符號聲明與符號定義不一樣。
5.
使用了一個函數,但其參數的類型或數量與函數定義不匹配。
函數聲明使用和函數定義使用中的調用約定(__cdecl、__stdcall 或 __fastcall)不一樣。
6.
符號定義在編譯爲 C 程序的文件中,而符號是在 C++ 文件中不帶 extern "C" 修飾符聲明的。在此狀況下,請修改聲明,例如不是使用:
extern int i;
extern void g();
而使用:
extern "C" int i;
extern "C" void g();
一樣,若是在將由 C 程序使用的 C++ 文件中定義符號,請在定義中使用 extern "C"。
7.
符號定義爲靜態,但稍後在文件外部被引用。
沒有定義靜態類成員。例如,應單獨定義下面類聲明中的成員變量 si:
#include <stdio.h>
struct X {
static int si;
};
// int X::si = 0; // uncomment this line to resolve
void main()
{
X *px = new X[2];
printf("n%d",px[0].si); // LNK2019
}
8.
也可能因爲爲 Visual Studio .NET 2003 進行的一致性工做生成此錯誤:模板友元和專用化。在 Visual Studio .NET 2003 中,必須定義聲明新的非模板函數的友元聲明。
要使代碼在 Visual C++ 的 Visual Studio .NET 2003 和 Visual Studio .NET 版本中均有效,請顯式指定友元函數的模板參數列表。
// LNK2019.cpp
// LNK2019 expected
template<class T>
void f(T)
{
}
template<class T>
struct S
{
friend void f(T);
// Try the folowing line instead:
// friend void f<T>(T);
};
int main()
{
S<int> s;
f(1); // unresolved external
}
/VERBOSE 連接器選項幫助您查看連接器引用的文件。DUMPBIN 實用工具的 /EXPORT 和 /SYMBOLS 選項還能夠幫助您查看 dll 和對象/庫文件中定義的符號。
-------------------------------------
例如「error LNK2019: 沒法解析的外部符號_imp__SetupDiGetDeviceInterfaceDetailW@24
error LNK2001: 沒法解析的外部符號「private: static struct _OVERLAPPED CUsbCom::g_WriteOverlapped」
應該是工程設置的問題 沒有鏈接相應的lib庫或者是所用到的函數沒定義(這個定義是在別的類裏面的)
當出現error LNK2001: 沒法解析的外部符號 _print_interface log.obj 可在log.c裏搜print_interface(無前面_),找到此函數,看有無定義學習VC++時常常會遇到連接錯誤LNK2001,該錯誤很是討 厭,由於對於 編程者來講,最好改的錯誤莫過於編譯錯誤,而通常說來發生鏈接錯誤時,編譯都已經過。產生鏈接錯誤的緣由很是多,尤爲LNK2001錯誤,經常令人不 明其因此然。若是不深刻地學習和理解VC++,要想改正鏈接錯誤LNK2001非 常困難。
初學者在學習VC++的過程當中,遇到的LNK2001錯誤的錯誤消息主要爲:
unresolved external symbol 「symbol」(不肯定的外部「符號」)。 若是鏈接程序不能在全部的庫和目標文件內找到所引用的函數、變量或 標籤,將產生此錯誤消息。通常來講,發生錯誤的緣由有兩個:一是所引用 的函數、變量不存在、拼寫不正確或者使用錯誤;其次可能使用了不一樣版本的鏈接庫。
如下是可能產生LNK2001錯誤的緣由:
一.因爲編碼錯誤致使的LNK2001。
1.不相匹配的程序代碼或模塊定義(.DEF)文件能致使LNK2001。例如, 若是在C++ 源文件內聲明瞭一變量「var1」,卻試圖在另外一文件內以變量 「VAR1」訪問該變量,將發生該錯誤。
2.若是使用的內聯函數是在.CPP文件內定義的,而不是在頭文件內定義將致使LNK2001錯誤。
3.調用函數時若是所用的參數類型同函數聲明時的類型不符將會產生 LNK2001。
4.試圖從基類的構造函數或析構函數中調用虛擬函數時將會致使LNK2001。
5.要注意函數和變量的可公用性,只有全局變量、函數是可公用的。
靜態函數和靜態變量具備相同的使用範圍限制。當試圖從文件外部訪問任何沒有在該文件內聲明的靜態變量時將致使編譯錯誤或LNK2001。函數內聲明的變量(局部變量) 只能在該函數的範圍內使用。
C++ 的全局常量只有靜態鏈接性能。這不一樣於C,若是試圖在C++的 多個文件內使用全局變量也會產生LNK2001錯誤。一種解決的方法是須要時在頭文件中加入該常量的初始化代碼,並在.CPP文件中包含該頭文件;另外一種 方法是使用時給該變量賦以常數。
二.因爲編譯和連接的設置而形成的LNK2001
1.若是編譯時使用的是/NOD(/NODEFAULTLIB)選項,程序所須要的運行庫和MFC庫在鏈接時由編譯器寫入目標文件模塊, 但除非在文件中明確包含 這些庫名,不然這些庫不會被連接進工程文件。在這種狀況下使用/NOD將導 致錯誤LNK2001。
2.若是沒有爲wWinMainCRTStartup設定程序入口,在使用Unicode和MFC時將獲得「unresolved external on _WinMain@16」的LNK2001錯誤信息。
3.使用/MD選項編譯時,既然全部的運行庫都被保留在動態連接庫以內,源文件中對「func」的引用,在目標文件裏即對「__imp__func」 的引用。
若是試圖使用靜態庫LIBC.LIB或LIBCMT.LIB進行鏈接,將在__imp__func上發 生LNK2001;若是不使用/MD選項編譯,在使用MSVCxx.LIB鏈接時也會發生LNK2001。
4.使用/ML選項編譯時,如用LIBCMT.LIB連接會在_errno上發生LNK2001。
5.當編譯調試版的應用程序時,若是採用發行版模態庫進行鏈接也會產生LNK2001;一樣,使用調試版模態庫鏈接發行版應用程序時也會產生相同的 問題。
6.不一樣版本的庫和編譯器的混合使用也能產生問題,由於新版的庫裏可 能包含早先的版本沒有的符號和說明。
7.在不一樣的模塊使用內聯和非內聯的編譯選項可以致使LNK2001。若是建立C++庫時打開了函數內聯(/Ob1或/Ob2),可是在描述該函數的相應 頭文件裏卻關閉了函數內聯(沒有inline關鍵字),這時將獲得該錯誤信息。 爲避免該問題的發生,應該在相應的頭文件中用inline關鍵字標誌內聯函數。
8.不正確的/SUBSYSTEM或/ENTRY設置也能致使LNK2001。 其實,產生LNK2001的緣由還有不少,以上的緣由只是一部分而已,對初 學者來講這些就夠理解一陣子了。可是,分析錯誤緣由的目的是爲了不錯 誤的發生。LNK2001錯誤雖然比較困難,可是隻要注意到了上述問題,仍是可以避免和予以解決的。
既然編譯經過了,就說明了沒有語法錯誤,不用在代碼中死摳語法了。從錯誤中提示中找緣由吧。
通常問題出在
(1)XXX.lib頭文件,這個要包含(否則編譯也不能經過)
(2)須要XXX.lib或XXX.dll庫。手動添加,項目->屬性->配置屬性->連接器->輸入 而後在附件依賴項添加XXX.lib,再生成第一個沒法解析的外部符號錯誤消失了。
================================================================
1八、Visual Studio 2005不能進行調試,錯誤126: 找不到指定的模塊
================================================================
在資源視圖中右擊對話框ID,選屬性,修改語言設置
================================================================
1>e:program filesmicrosoft visual studio 9.0vcatlmfcincludeafxtempl.h(776) : error C2248: 'CObject::operator =' : cannot access private member declared in class 'CObject'
1> e:program filesmicrosoft visual studio 9.0vcatlmfcincludeafx.h(562) : see declaration of 'CObject::operator ='
1> e:program filesmicrosoft visual studio 9.0vcatlmfcincludeafx.h(532) : see declaration of 'CObject'
1> This diagnostic occurred in the compiler generated function 'CList<TYPE,ARG_TYPE> &CList<TYPE,ARG_TYPE>::operator =(const CList<TYPE,ARG_TYPE> &)'
1> with
1> [
1> TYPE=CProgram,
1> ARG_TYPE=CProgram &
1> ]
上面這段編譯器報警是否是有似曾相識的感受?想必不少人在用VC2005以及以後的版本的VC編譯器時看到過這個東西,在google查一下error C2248: 'CObject::operator =' : cannot access private member declared in class 'CObject'你會發現不少人碰到相似的問題。一位叫「中國民工」的blog中說明了引起這一問題的的緣由,請參見http://www.cppblog.com/hlong/archive/2007/11/20/37015.html
根據民工兄的解釋,因爲咱們的類中定義了CArray類型的成員,而CArray<A, A&>類的operator=是private類型(它繼承自CObject::operator=,且被定義爲private類型)。並給出瞭解決之道:若是咱們的類/結構體中有CArray(或CList等其餘的派生自CObject類)的成員變量,咱們最好添加上一個public類型的operator=運算賦重載函數;
問題雖然是解決了,可是彷佛仍是沒弄明白產生問題的根本緣由:既然問題是因爲CArray沒有定義Operator=操做從而致使須要調用基類CObject中的私有Operator= 操做而引發的,那麼爲何微軟要將CObject的Operator=操做定義成私有呢?或者說爲何CObject在實際上並無對Operator= 和拷貝構造函數作任何實質性的定義的狀況下要去定義這兩個函數,而且還將他們定義爲private。。惟一的解釋就是微軟不但願繼承自CObject的類 使用默認的Operator=操做,或者說微軟不但願使用了CArray或者CList或者CMap的Collections模板類的類使用默認的Operator=操做。答案的確是如此,不只如此,對於默認的拷貝構造函數結論也是同樣(可能有些人碰到到一樣的編譯器報錯,不過是針對拷貝構造函數的,後面我會解釋引起這兩種類型的報錯的真正緣由)。
要想搞清楚這個問 題,就先要了解C++編譯器生成的默認函數——這些咱們平時一直在使用卻不多關心的幕後工做者究竟是怎樣工做的。當咱們建立一個C++變量,爲一個變量賦 值,或者調用一個C++函數,或者對一個C++變量進行取地址&操做時,這些都是一些基本操做,咱們老是能獲得咱們想要的結果(至少看起來是這 樣)由於這些都是C++的語義,而負責實現這些語義的是C++編譯器。
編譯器又是如何實 現這些語義的呢,好比當你構造一個C++變量時,編譯器會檢查你有沒有爲這個變量的類型建立一個構造函數,若是沒有,編譯器會本身幫你生成一個默認的構造 函數,從而實現了一個C++變量的構造;相似的,在用戶執行其餘一些諸如賦值操做,拷貝構造,取地址等基本操做時,編譯器遵循一樣的原則,即在用戶未定義 相應的操做狀況下自動生成一個默認的操做;正由於如此,甚至不少程序員並不知道它們的存在(我記得幾年前我去一家公司面試的時候,就被問及過這樣一個問題:C++類的默認函數有幾個,分別是什麼,,其實這是一個蠻深入的問題),即便知道它們,也會以爲在不須要咱們付出任何關心的狀況下,這些操做都是理所應當應該是正確的,可是事實並不是老是如此。
Effective C++在條款45也對這幾個函數進行了比較詳細的分析;其中構造函數和析構函數其實就是一個空函數,什麼也不作,因此當咱們用VC也好或者其餘的C++編 譯器建立一個空類也好,編譯器都會爲咱們的類事先定義一個構造和析構函數,就是爲了避免讓咱們去使用默認的構造和析構函數。因此通常狀況下咱們不多會忽視這 兩個函數的存在,可是另外3個很重要的函數:拷貝構造和賦值操做符,以及取地址操做符就很容易被忽視掉,由於咱們不多去實現這3個操做,大部分都是使用的 編譯器提供的默認的實現。
對於默認賦值操做符和拷貝構造函數的默認實現,Effective C++上的解釋是:官 方的規則是:缺省拷貝構造函數(賦值運算符)對類的非靜態數據成員進行 "以成員爲單位的" 逐一拷貝構造(賦值)。即,若是m是類C中類型爲T的非靜態數據成員,而且C沒有聲明拷貝構造函數(賦值運算符),m將會經過類型T的拷貝構造函數(賦值 運算符)被拷貝構造(賦值)---- 若是T有拷貝構造函數(賦值運算符)的話。若是沒有,規則遞歸應用到m的數據成員,直至找到一個拷貝構造函數(賦值運算符)或固定類型(例 如,int,double,指針,等)爲止。默認狀況下,固定類型的對象拷貝構造(賦值)時是從源對象到目標對象的 "逐位" 拷貝。對於從別的類繼承而來的類來講,這條規則適用於繼承層次結構中的每一層,因此,用戶自定義的構造函數和賦值運算符不管在哪一層被聲明,都會被調用。
另一個很重要的概念是:當且僅當相應的操做被定義時,編譯器才爲操做變量所屬的類型生成對應的默認操做;也就是說,若是代碼中沒有出現相應的操做,編譯器什麼也不會作。
再回到咱們一開始民工兄的例子中,假設咱們的類C中定義了一個CArray類型的成員變量,而且C中沒有顯示的定義operator=操做(這就意味着編譯器可能須要爲C自動生成一個默認的operator=操做)根據上面的說法,當且僅當C的實例被賦值時編譯器纔會生 成默認的operator=操做,而編譯器報警告訴咱們,編譯器在生成operator=操做時遇到了障礙,這個障礙就是:C的CArray成員具備一個 賦值運算符定義,可是該定義是私有的(其實是CArray繼承自CObject的operator=定義)。。咱們看一下民工兄的例子的源碼:
3struct A
4{
5 int a;
6};
7
8struct B
9{
10 CArray<A, A&> b;
24};
25
26 typedef CArray<B, B&> C;
27
28void test()
29{
30 B b;
31 C c;
32 c.Add(b);
33 }
從這段代碼中能夠看出,test中對B的實例b並無作任何賦值的操做,爲何編譯器會去實現B的默認operator=操做呢?
問題就處在CArray::Add()的函數簽名身上,Add函數的源碼以下
template<class TYPE, class ARG_TYPE>
AFX_INLINE INT_PTR CArray<TYPE, ARG_TYPE>::Add(ARG_TYPE newElement)
{ INT_PTR nIndex = m_nSize;
SetAtGrow(nIndex, newElement);
return nIndex; }
可見,形參newElement的類型是ARG_TYPE,ARG_TYPE其實就是TYPE的引用,在這裏就是B的引用;答案彷佛明瞭了:
由於Add函數的簽名要求輸入參數的類型爲B&,因此當編譯器編譯語句:c.Add(b); 時會自動將b強制轉換成B的引用,即將這條語句編譯成:B& d = b; c.Add(d); 賦值操做就這樣出現了!
爲了驗證這個想法,能夠作另外一個測試,調用一個傳值的函數,這樣就不須要作「B& d = b;」的轉換了,那麼就應該不會有問題了。
很不幸,實際上編譯器會報一樣的錯誤,只是如今不是operator=而是拷貝構造函數。
原 因很簡單,由於對於傳值的方式,實際上就是「經過值來傳遞一個對象」,而這又是由這個對象的類的拷貝構造函數定義的。也就是說當經過傳值的方式調用一個子 程序時,最終是編譯器經過調用拷貝構造函數來實現的。因此問題是同樣的,由於類型B沒有定義本身的拷貝構造函數,因而編譯器試圖生成一個默認的,但它一樣 遇到了障礙,由於CArray的拷貝構造也是private的(一樣繼承於CObject)。
至此,咱們對於這個問題有了一個比較全面的認識,其實問題的本質在於:不管是默認的operator=仍是默認的拷貝構造也好都是有其致命的缺陷的,正如Effective C++條款11中所描述的,當這些默認的實如今遇到須要動態分配內存的類的時候就會出現問題,也就是所謂的深拷貝問題。而Collections模板類就是典型的不能使用默認operator=和默認的拷貝構造的例子。
因此當咱們自定義的類中包含Collections模板類的成員時咱們就無法再偷懶使用編譯器自動生成的operator=和的拷貝構造了,而必須本身動手實現,這也是微軟想提醒咱們的一個事實。
在windows console下編譯 的時候遇到這個問題的
using namespace std;
#include <iostream>
using namespace std;
編譯時提示error C2065: 「IDD_DIALOG1」 : 未聲明的標識符
錯誤的可能緣由及解決方法以下:
1.出錯文件中沒有包含資源文件ID聲明的resource.h文件。在出錯文件中加入#include 「resource.h」語句。
2.工程附件包含目錄的路徑下沒有resource.h文件。修改路徑便可。
3.工程所在文件夾下存在resource.h文件,但其中沒有資源ID的定義, 致使真正的resource.h沒有包含進去,刪除之。一個解決方案裏面有多個工程,可能會把全部資源ID的聲明放到一個文件中。在各個工程中實現對話框 功能的文件中,只需包含該文件便可。可是,當新增某個資源之後,工程中會自動生成一個resource.h(不知道爲何會這樣),而不是在已有的 resource.h文件中添加ID的定義。因爲工程編譯的時候先從本地搜索頭文件,會包含了自動生成的頭文件,因而出現了上述錯誤。
注意:若是是智能設備程序出現此錯誤,應該確保resourceppc.h和Resourceppc.h中都有相同的宏定義#define IDD_DIALOG1 XXX,而且在dialog.cpp中包含資源頭文件resourceppc.h
==============================================================
二、error C2471: 沒法更新程序數據庫 ,fatal error C1083: 沒法打開程序數據庫文件
fatal error C1083: 沒法打開程序數據庫文件:「c:documents and settings........debugvc90.pdb」: No such file or directory ....
解決方法:
修改一下設置,就能夠解決C2471:
CC++ | General | Debug Information format | C7 Compatible (/Z7)
CC++ | Code Generation | Enable String Pooling | Yes (/GF)
Linker | General Debug Info | Yes (/DEBUG)
或者把在debug文件夾下的.pdb文件給刪除了,f5一下就好了
================================================================
三、error沒法打開預編譯頭文件的解決方法及預編譯頭原理
1。用VC.NET編輯程序,按Ctrl+F7,出現下列錯誤:
fatal error C1083: 沒法打開預編譯頭文件:「Debug/UGFace.pch」: No such file or directory
解決方法:修改:項目->屬性->C/C++ ->預編譯頭->不使用預編譯頭 便可。
2。學用Visual C++ 6.0的第一個例程就讓我出了錯.用嚮導生成第一個基於對話框的Project以後,當我按照書上的源程序一個字一個字地輸進去以後,始終有一個錯誤:
fatal error C1010: unexpected end of file while looking for precompiled header directive.找了無數次以後,我決定把嚮導生成的包括頭文件的語句:include"StdAfx.h"保留(而這以前我是把它刪掉了的,由於書 上的例子沒有這句.)咦,這下就對了.這是爲何呢?我百思不得其解。
來 到個人VC源代碼目錄,我注意到每一個Project下面的DEBUG文件夾都特別大,並且一個擴展名爲 .pch的文件佔去了絕大部分,我刪掉之好像對程序編譯運行沒有什麼影響。因而抱着對.pch文件的好奇,我在網上搜到了我疑惑之處的解答。這就是 VC++6.0給咱們帶來的:預編譯頭文件。預編譯頭文件(通常擴展名爲.PCH),是把一個工程中較穩定的代碼預先編譯好放在一個文件(.PCH)裏。 這些預先編譯好的代碼能夠是任何的C/C++代碼,甚至能夠是inline函數,只是它們在整個工程中是較爲穩定的,即在工程開發過程當中不會常常被修改的 代碼。
爲何須要預編譯頭文件?
一 言以蔽之:提升編譯速度.通常地,編譯器以文件爲單位編譯。若是修改了一工程中的一個文件則全部文件都要從新編譯,包括頭文件裏的全部東西 (eg.Macro宏,Preprocessor預處理),而VC程序中,這些頭文件中所包括的東西每每是很是大的,編譯之將佔很長的時間。但它們又不常 被修改,是較穩定的,爲單獨的一個小文件而從新編譯整個工程的全部文件致使編譯效率降低,所以引入了.PCH文件。
如何使用預編譯頭文件以提升編譯速度?
要 使用預編譯頭文件,必須指定一個頭文件(.H),它包含咱們不會常常修改的代碼和其餘的頭文件,而後用這個頭文件來生成一個預編譯頭文件 (.PCH),VC默認的頭文件就是StdAfx.h,由於頭文件是不能編譯的,因此咱們還須要一個.CPP文件來做橋樑,VC默認的文件爲 StdAfx.cpp,這個文件裏只有一句代碼就是:#include "StdAfx.h"。接下來要用它生成.PCH文件,涉及到幾個重要的預編譯指令:/Yu,/Yc,/Yx,/Fp。簡單地說,/Yc是用來生 成.PCH文件的編譯開關。在Project->setting->C/C++的Category裏的Precompiled Header,而後在左邊的樹形視圖中選擇用來編譯生成.PCH文件的.CPP文件(默認即StdAfx.cpp),你 就能夠看到/Yc這個開關,它表示這個文件編譯了之後是否生成.PCH文件(可能/Yc的c表示create)。/Fp指令指定生成的.PCH文件的名字 及路徑(可能/Fp的p表明path)。/Yu的u即use,工程中只要包括了.H文件的文件都會有這個/Yu指令。若是選擇自動 Automatic...的話則原來爲/Yc的地方就換成了/Yx指令。若是選擇自動,則每次編譯時編譯器會看之前有沒有生成過.PCH文件,有則不現生 成不然就再次編譯產生.PCH文件。
注意:
A, 實際上,由Appzard項目嚮導生成的默認的頭文件及CPP文件StdAfx.h和StdAfx.cpp能夠是任何名字的.緣由很簡單。但若是你要這樣 作就要記得修改相應的Project->setting...下的幾個預編譯指(/Yc,/Yu,/Yx,/Fp)的參數。
B. 在任何一個包括了將要預編譯的頭文件而使用了.PCH文件的工程文件的開頭,必定必需要是在最開頭,你要包含那個指定生成.PCH文件的.H文件(通 過.CPP文件包括,默認爲StdAfx.cpp),若是沒包括將產生我最開頭產生的錯誤.若是不是在最開頭包括將產生讓你意想不到的莫名其妙錯誤,如若 不信,盍爲試之?
C.預編譯文件.PCH生成之很耗時間,並且生成以後它也很佔磁盤空間,常在5-6M,注意項目完成以後及時清理無用的.PCH文件以節約磁盤空間。
D.若是丟了或刪了.PCH文件而之後要再修改工程文件時,可將指定的/Yc的.CPP文件(默認爲StdAfx.cpp)從新編譯一次便可再次生成.PCH文件,不用傻傻的按F7或Rebuild All
以 前還碰到過另一種狀況:新建一個工程,隨便找一個cpp文件,按ctrl+f7系統將會提示:fatal error C1083: 沒法打開預編譯的頭文件:」Debug/xxx.pch」: No such file or directory(其中xxx是工程的名字)這種狀況也是同樣的緣由,爲vc的stdafx.h頭文件未編譯所致。也能夠這樣解決:先F7,編譯後再 ctrf+f7。
vc2005error:沒法執行添加/移除操做,由於代碼元素是隻讀的
出現這種現象,多數是由於你的工程所在文件夾的屬性設置爲了「只讀」,你能夠關閉解決方案,而後從新打開,就能夠了,若是之後不想出現這樣的狀況,把工程所在的文件夾屬性中的「只讀」去掉,就能夠了。
解決方案:
一、重啓VS2005
二、查看.h和.cpp文件的屬性,有多是隻讀的,修改屬性後就能夠了
三、打開Resource.h文件看看 一看就知道了 有些定義重複了 能夠手動改掉 保存 編輯器從新加載
四、把你要添加事件的對話框相應的類文件(*.h和*.cpp)給關了就能夠了
五、關閉解決方案,刪除.ncb文件從新添加便可
六、實在不行就手動添加消息處理
在BEGIN_MESSAGE_MAP(。。。)
//這裏要刪掉你原先已經增長過的消息隱射函數
END_MESSAGE_MAP()
================================================================
五、程序運行出現-1.#IND,1.#INF
INF就是infinite,就是無窮大的意思
IND可能表示很小,不肯定
//////////////////////////////////////////////////////////
使用相似於pow, exp等等函數時常會產生一個無效數字1.#IND00,在VC下能夠經過與一個肯定數字比較大小來判斷是否產生了無效數字,但這個方法在DEV-CPP下倒是行不通的。
其實解決辦法很簡單,使用 float.h中一個函數_isnan便可:
int _isnan(double x);
當x是一個無效值(NaN, Not a Number) 時,返回非零值
不然返回0
================================================================
六、LINK : 上一個增量連接沒有生成它;正在執行徹底連接
代碼
#include"iostream"
using namespace std;
int main()
{
cout<<"123";
return 0;
}
LINK : 沒有找到 D:Visual Studio 2008ProjectstestDebugtest.exe 或上一個增量連接沒有生成它;正在執行徹底連接
在對話框中類中添加對CListCtrl控件右鍵處理的時候出現以下錯誤:
error C2440: 'reinterpret_cast' : cannot convert from 'NMHDR *' to 'NMITEMACTIVATE' Conversion requires a constructor or user-defined-conversion operator, which can't be used by const_cast or reinterpret_cast
須要把:LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<NMITEMACTIVATE>(pNMHDR);
; 改成: LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<NMITEMACTIVATE*>(pNMHDR);
參考:http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=339678
================================================================
八、沒法解析的外部符號 _WinMain,該符號在函數 ___tmainCRTStartup 中被引用
一,問題描述
MSVCRTD.lib(crtexew.obj) : error LNK2019: 沒法解析的外部符號_WinMain@16,該符號在函數 ___tmainCRTStartup 中被引用
Debugjk.exe : fatal error LNK1120: 1 個沒法解析的外部命令
error LNK2001: unresolved external symbol_WinMain@16
debug/main.exe:fatal error LNK 1120:1 unresolved externals
error executing link.exe;
二,產生這個問題可能的緣由
產生這個問題的真正緣由是c語言運行時找不到適當的程序入口函數,通常狀況下,若是是windows程序,那麼WinMain是入口函數,若是是dos控制檯程序,那麼main是入口函數,而若是入口函數指定不當,很顯然c語言運行時找不到配合函數,它就會報告錯誤。
可能:
1, 你用vc建了一個控制檯程序,它的入口函數應該是main, 而你使用了WinMain.
2. 你用vc打開了一個.c/.cpp 文件,而後直接編譯這個文件,這個文件中使用了WinMian而不是main做爲入口函數。vc這時的默認設置是針對控制檯程序的。
3.根本就沒有WinMain或Main函數。
三, 解決方法
1.進入project->setting->c/c++, 在category中選擇preprocessor,在processor definitions中刪除_CONSOLE, 添加_WINDOWS
2.進入project->setting->Link, 在Project options中將 /subsystem:console改成/subsystem:windows.
3.保存設置,Rebuild All.
四,VS2008中的設置
1.菜單中選擇 Project->Properties, 彈出Property Pages窗口
2.在左邊欄中依次選擇:Configuration Properties->C/C++->Preprocessor,而後在右邊欄的Preprocessor Definitions對應的項中刪除_CONSOLE, 添加_WINDOWS.
3.在左邊欄中依次選擇:Configuration Properties->Linker->System,而後在右邊欄的SubSystem對應的項改成Windows(/SUBSYSTEM:WINDOWS)
4.Rebuild All. Ok ?
================================================================
九、fatal error LNK1112: 模塊計算機類型「ARM」與目標計算機類型「X86」衝突
fatal error LNK1112: 模塊計算機類型「ARM」與目標計算機類型「X86」衝突
解決方法:連接器 -> 命令行 -> 附加選項, 添加 /MACHINE:ARM /MACHINE:THUMB
fatal error LNK1112: 模塊計算機類型「THUMB」與目標計算機類型「ARM」衝突
解決方法:
第1種:連接器 -> 命令行 -> 附加選項, 添加 /MACHINE:THUMB
第2種:新建項目時,在"平臺"->"選擇要添加到當前項目中的 Platform SDK。"中,把"已安裝的 SDK"所有添加到"選定的 SDK"
若是是直接使用已經建立好的工程,那麼第一種方法就能夠解決了,實在不行,就只有採用第二種辦法從頭解決了 。
================================================================
十、error c3872: 「0x3000」: 此字符不容許在標識符中使用
例如friend ostream& operator<<(ostream& out,const Chain<T>& x );
出錯error c3872: 「0x3000」: 此字符不容許在標識符中使用
解決方法:
0x3000是漢語的空格,也就是全角空格,至關於一個漢字,但你又看不見它。
像逗號,有半角(,)和全角(,)之分的,其實空格也有。
0x3000是全角的空格,0x20是半角的空格。
你最好把這個語句的後面空白部分都刪除掉,並檢查是否有中文標點存在。
================================================================
十一、0x????處未處理的異常:0xC0000005
使用VC編碼的時候常常會出現「Test.exe 中的 0x00414030 處未處理的異常: 0xC0000005: 寫入位置 0xfeeefeee 時發生訪問衝突 。」
出現0xC0000005的緣由通常都是沒有分配內存 或者 內存無效 所致,
例如:
#include "stdafx.h"
#include <string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
string * s = NULL;
s = new string();
delete s;
if (s != NULL)
{
*s = "TEST"; //這步操做將引發異常。
}
return 0;
}
雖然s已經被delete了,可是s的值並不爲NULL,if語句的判斷將失效,這是新手常見的一個錯誤!
爲了防止這個錯誤能夠本身定義一個宏來處理delete。
#define _DELETE(obj) if (obj != NULL) {delete obj , obj = NULL;}
使用這個宏能夠防止相似錯誤出現。
================================================================
十二、沒有找到MFC80UD.DLL,所以這個程序未能啓動.從新安裝應用程序可能會修復此問題
在vs2005 sp1中文版中,在「解決方案資源管理器」中的項目上右擊,選擇「屬性」,找到「配置屬性」中的「連接器」,而後找到「清單文件」,在右邊的屬性框中,默認「生成清單」項爲「是」,選 把「是」改爲「否」,運行之,出錯,而後再把否改回來,OK。
其餘:
(1)若是不選"系統菜單"和"關於菜單"就不會有這個問題!
(2)若是在"工程屬性->配置屬性->常規->字符集"選"使用多字節字符集"也不會出這個問題!
(3)好像是刪除全部的中間文件,(具體一點說,就是刪除."(工程文件)"Debug裏的文件和.ncb),再"從新生成解決方案文件...",可能能夠.
(4)clean關閉vs,打開rebuild應該就能夠了,個人不多遇到。遇到以後這樣就解決了。不行就多試幾回。
(5)linker-》manifest-file-》Generate Manifest: Yes
(6)Manifest搞的鬼,而後修改項目屬性,清單工具中的輸入輸出把嵌入清單文件選否.而後編譯,連接運行,成功
debug---動態使用dll
release---靜態使用dll
debug狀態下使用,會時不時出這個問題;
release狀態下使用,不會出現這個問題。
================================================================
1三、沒有找到MFC80D.DLL或msvcr80d.dll的解決方法
解決方案:
在編輯狀態下,點項目菜單 -> XXX屬性頁 -> 配置屬性 -> 清單工具,將右面的「使用FAT32解決辦法」選爲「是」便可。簡單地,其實把程序目錄下的Debug目錄整個刪掉,再讓VS所有從新生成文件也能解決這個問題,只是可能再犯。
沒有找到MFC80D.DLL的解決方法。問題出如今程 序運行清單上,默認是"嵌入清單",清單文件是"$(IntDir$(TargetFileName).embed.manifest"。調試程序運行 時,不知道爲何卻定位不到這個文件,咱們若是手動把"程序名.embed.manifest"改成"程序名.manifest",調試程序便可定位到。
其餘
方法一:
在C:Program FilesMicrosoft Visual Studio 8VCredi
stDebug_NonRedistx86Microsoft.VC80.DebugCRT 下找到了下列文件:
msvcm80d.dll
msvcp80d.dll
msvcr80d.dll
Microsoft.VC80.DebugCRT.manifest
把這幾個文件拷貝到目標機器上,與運行程序同一文件夾或放到system32下,就能夠運行那個程序了。
方法二:
修改編譯選項,將/MD或/MDd 改成 /MT或/MTd,這樣就實現了對VC運行時庫的靜態連接,在運行時就再也不須要VC的dll了。
================================================================
1四、fatal error LNK1181: 沒法打開輸入文件「..filename.lib」
================================================================
1五、沒有找到MFC80D.DLL,所以這個程序未能啓動.從新安裝應用程序可能會修復此問題
解決方法:刪除程序目錄下Debug文件夾和Release文件夾,而後從新編譯執行。
===網上其餘方法=============
方法一:
沒 有找到MFC80D.DLL的解決方法。問題出如今程序運行清單上,默認是"嵌入清單",清單文件是 "$(IntDir$(TargetFileName).embed.manifest"。調試程序運行時,不知道爲何卻定位不到這個文件,咱們若是 手動把"程序名.embed.manifest"改成"程序名.manifest",調試程序便可定位到。
方法二:
在C:Program FilesMicrosoft Visual Studio 8VCredistDebug_NonRedistx86Microsoft.VC80.DebugCRT 下找到了下列文件:
msvcm80d.dll
msvcp80d.dll
msvcr80d.dll
Microsoft.VC80.DebugCRT.manifest
把這幾個文件拷貝到目標機器上,與運行程序同一文件夾或放到system32下,就能夠運行那個程序了。
方法三:
修改編譯選項,將/MD或/MDd 改成 /MT或/MTd,這樣就實現了對VC運行時庫的靜態連接,在運行時就再也不須要VC的dll了。
================================================================
1六、mspdb80.dll沒法找到的解決方法
在cmd中鍵入cl執行編譯時會出現mspdb80.dll沒法找到的狀況,是由於VCBin下沒有「msobj80.dll,mspdb80.dll,mspdbcore.dll,mspdbsrv.exe」這四個文件,解決的方法:
1>直接從Microsoft Visual Studio 8Common7IDE下複製這四個文件到Microsoft Visual Studio 8VCBin下便可解決
2> 添加系統變量(Path),這樣:個人電腦->屬性->高級->環境變量->系統變量,在path中添加C:Program FilesMicrosoft Visual Studio 8Common7IDE;,注意結尾最後用「;」隔開!
這樣在用cl編譯就不會出現mspdb80.dll文件找不到的錯誤了。
================================================================
1七、error LNK2019: 沒法解析的外部符號....該符號在函數 ...中被引用
這種狀況通常都是函數只找到聲明但沒有實現,或者是少了什麼連接庫,你能夠試試把那兩個.h和.c文件直接加入工程中再試試。
有一個解決方案,有兩個工程A,B。工程B中定義了一個類,在工程A的demo.cpp中引用該類,可是若是是
#include "XX,h",則會出現「error LNK2019: 沒法解析的外部符號」
若是是#include "XX.cpp",則能夠順利編譯經過。
想來是由於引用 .h 文件致使找不到.cpp中的定義,而引用.cpp能夠經過.cpp找到.h(.cpp有對.h的include)
可是若是同在工程B下面,則#include "XX,h"也是正確的,它會自動關聯到同名的(反正是對應的).cpp文件。
在不一樣工程中應該如何引用呢?
看見一種緣由分析,以下:
現場狀況:
funcname 在文件file.cpp/h中定義實現
void funcname(void) {;}
filecall.c文件內呼叫funcname()函數。
出現上面狀況。
症因:因c/c++混合編程, c文件內函數沒法呼叫c++文件內函數。
解決,或者將c文件名改成.cpp,或者將c++文件名改成.c
上面的解決採用將 file.cpp 改名爲file.c便可。
1.
在 Visual C++ .NET 2003 中,若是使用了 /clr 而未將 CRT 連接到可執行文件,將生成此錯誤。任何由編譯器在未使用 /clr:initialAppDomain 時生成的對象代碼都包含對 _check_commonlanguageruntime_version 函數的引用,該函數在 C 運行時庫 (CRT) 中定義。若是應用程序在運行庫的版本 1 上運行,該函數將會生成一個錯誤信息。當前編譯器生成的代碼與運行庫的版本 1 不兼容。所以,若是在 Visual C++ .NET 2003 中編譯時不使用 CRT,則應在代碼中包含 _check_commonlanguageruntime_version 函數的定義。做爲使用 _check_commonlanguageruntime_version 函數的替代方法,您能夠與 nochkclr.obj 連接。nochkclr.obj 包含該函數的一個空版本,當您在運行庫的版本 1 上運行應用程序時,nochkclr.obj 不生成錯誤信息。若要使用當前編譯器版本生成應用程序以在運行庫的之前版本上運行,應使用 /clr:InitialAppDomain。
若要 生成一個純 MSIL 可執行文件(不與 CRT 連接),則必須在項目中定義該函數,而不能使用 nochkclr.obj(.obj 是本機代碼)。有關可驗證代碼的更多信息,請參見產生可驗證的 C++ 託管擴展組件。有關從託管 C++ 項目建立純 MSIL 輸出文件的更多信息,請參見將 C++ 託管擴展項目從混合模式轉換成純 IL。
2.
請看下面的示例:
extern int i;
extern void g();
void f()
{
i++;
g();
}
int main()
{
}
若是在生成中包含的某個文件中沒有定義 i 和 g,連接器將生成 LNK2019。能夠添加這些定義,方法是將包含這些定義的源代碼文件包括爲編譯的一部分。或者能夠將包含這些定義的 .obj 或 .lib 文件傳遞給連接器。
3.
對於從早期版本升級到當前版本的 C++ 項目,若是定義了 __UNICODE 而且入口點爲 WinMain,須要將入口點函數的名稱更改成 _tWinMain 或 _tmain。
4.
符號聲明包含拼寫錯誤,以至於符號聲明與符號定義不一樣。
5.
使用了一個函數,但其參數的類型或數量與函數定義不匹配。
函數聲明使用和函數定義使用中的調用約定(__cdecl、__stdcall 或 __fastcall)不一樣。
6.
符號定義在編譯爲 C 程序的文件中,而符號是在 C++ 文件中不帶 extern "C" 修飾符聲明的。在此狀況下,請修改聲明,例如不是使用:
extern int i;
extern void g();
而使用:
extern "C" int i;
extern "C" void g();
一樣,若是在將由 C 程序使用的 C++ 文件中定義符號,請在定義中使用 extern "C"。
7.
符號定義爲靜態,但稍後在文件外部被引用。
沒有定義靜態類成員。例如,應單獨定義下面類聲明中的成員變量 si:
#include <stdio.h>
struct X {
static int si;
};
// int X::si = 0; // uncomment this line to resolve
void main()
{
X *px = new X[2];
printf("n%d",px[0].si); // LNK2019
}
8.
也可能因爲爲 Visual Studio .NET 2003 進行的一致性工做生成此錯誤:模板友元和專用化。在 Visual Studio .NET 2003 中,必須定義聲明新的非模板函數的友元聲明。
要使代碼在 Visual C++ 的 Visual Studio .NET 2003 和 Visual Studio .NET 版本中均有效,請顯式指定友元函數的模板參數列表。
// LNK2019.cpp
// LNK2019 expected
template<class T>
void f(T)
{
}
template<class T>
struct S
{
friend void f(T);
// Try the folowing line instead:
// friend void f<T>(T);
};
int main()
{
S<int> s;
f(1); // unresolved external
}
/VERBOSE 連接器選項幫助您查看連接器引用的文件。DUMPBIN 實用工具的 /EXPORT 和 /SYMBOLS 選項還能夠幫助您查看 dll 和對象/庫文件中定義的符號。
-------------------------------------
例如「error LNK2019: 沒法解析的外部符號_imp__SetupDiGetDeviceInterfaceDetailW@24
error LNK2001: 沒法解析的外部符號「private: static struct _OVERLAPPED CUsbCom::g_WriteOverlapped」
應該是工程設置的問題 沒有鏈接相應的lib庫或者是所用到的函數沒定義(這個定義是在別的類裏面的)
當出現error LNK2001: 沒法解析的外部符號 _print_interface log.obj 可在log.c裏搜print_interface(無前面_),找到此函數,看有無定義學習VC++時常常會遇到連接錯誤LNK2001,該錯誤很是討 厭,由於對於 編程者來講,最好改的錯誤莫過於編譯錯誤,而通常說來發生鏈接錯誤時,編譯都已經過。產生鏈接錯誤的緣由很是多,尤爲LNK2001錯誤,經常令人不 明其因此然。若是不深刻地學習和理解VC++,要想改正鏈接錯誤LNK2001非 常困難。
初學者在學習VC++的過程當中,遇到的LNK2001錯誤的錯誤消息主要爲:
unresolved external symbol 「symbol」(不肯定的外部「符號」)。 若是鏈接程序不能在全部的庫和目標文件內找到所引用的函數、變量或 標籤,將產生此錯誤消息。通常來講,發生錯誤的緣由有兩個:一是所引用 的函數、變量不存在、拼寫不正確或者使用錯誤;其次可能使用了不一樣版本的鏈接庫。
如下是可能產生LNK2001錯誤的緣由:
一.因爲編碼錯誤致使的LNK2001。
1.不相匹配的程序代碼或模塊定義(.DEF)文件能致使LNK2001。例如, 若是在C++ 源文件內聲明瞭一變量「var1」,卻試圖在另外一文件內以變量 「VAR1」訪問該變量,將發生該錯誤。
2.若是使用的內聯函數是在.CPP文件內定義的,而不是在頭文件內定義將致使LNK2001錯誤。
3.調用函數時若是所用的參數類型同函數聲明時的類型不符將會產生 LNK2001。
4.試圖從基類的構造函數或析構函數中調用虛擬函數時將會致使LNK2001。
5.要注意函數和變量的可公用性,只有全局變量、函數是可公用的。
靜態函數和靜態變量具備相同的使用範圍限制。當試圖從文件外部訪問任何沒有在該文件內聲明的靜態變量時將致使編譯錯誤或LNK2001。函數內聲明的變量(局部變量) 只能在該函數的範圍內使用。
C++ 的全局常量只有靜態鏈接性能。這不一樣於C,若是試圖在C++的 多個文件內使用全局變量也會產生LNK2001錯誤。一種解決的方法是須要時在頭文件中加入該常量的初始化代碼,並在.CPP文件中包含該頭文件;另外一種 方法是使用時給該變量賦以常數。
二.因爲編譯和連接的設置而形成的LNK2001
1.若是編譯時使用的是/NOD(/NODEFAULTLIB)選項,程序所須要的運行庫和MFC庫在鏈接時由編譯器寫入目標文件模塊, 但除非在文件中明確包含 這些庫名,不然這些庫不會被連接進工程文件。在這種狀況下使用/NOD將導 致錯誤LNK2001。
2.若是沒有爲wWinMainCRTStartup設定程序入口,在使用Unicode和MFC時將獲得「unresolved external on _WinMain@16」的LNK2001錯誤信息。
3.使用/MD選項編譯時,既然全部的運行庫都被保留在動態連接庫以內,源文件中對「func」的引用,在目標文件裏即對「__imp__func」 的引用。
若是試圖使用靜態庫LIBC.LIB或LIBCMT.LIB進行鏈接,將在__imp__func上發 生LNK2001;若是不使用/MD選項編譯,在使用MSVCxx.LIB鏈接時也會發生LNK2001。
4.使用/ML選項編譯時,如用LIBCMT.LIB連接會在_errno上發生LNK2001。
5.當編譯調試版的應用程序時,若是採用發行版模態庫進行鏈接也會產生LNK2001;一樣,使用調試版模態庫鏈接發行版應用程序時也會產生相同的 問題。
6.不一樣版本的庫和編譯器的混合使用也能產生問題,由於新版的庫裏可 能包含早先的版本沒有的符號和說明。
7.在不一樣的模塊使用內聯和非內聯的編譯選項可以致使LNK2001。若是建立C++庫時打開了函數內聯(/Ob1或/Ob2),可是在描述該函數的相應 頭文件裏卻關閉了函數內聯(沒有inline關鍵字),這時將獲得該錯誤信息。 爲避免該問題的發生,應該在相應的頭文件中用inline關鍵字標誌內聯函數。
8.不正確的/SUBSYSTEM或/ENTRY設置也能致使LNK2001。 其實,產生LNK2001的緣由還有不少,以上的緣由只是一部分而已,對初 學者來講這些就夠理解一陣子了。可是,分析錯誤緣由的目的是爲了不錯 誤的發生。LNK2001錯誤雖然比較困難,可是隻要注意到了上述問題,仍是可以避免和予以解決的。
既然編譯經過了,就說明了沒有語法錯誤,不用在代碼中死摳語法了。從錯誤中提示中找緣由吧。
通常問題出在
(1)XXX.lib頭文件,這個要包含(否則編譯也不能經過)
(2)須要XXX.lib或XXX.dll庫。手動添加,項目->屬性->配置屬性->連接器->輸入 而後在附件依賴項添加XXX.lib,再生成第一個沒法解析的外部符號錯誤消失了。
================================================================
1八、Visual Studio 2005不能進行調試,錯誤126: 找不到指定的模塊
================================================================
在資源視圖中右擊對話框ID,選屬性,修改語言設置
================================================================
1>e:program filesmicrosoft visual studio 9.0vcatlmfcincludeafxtempl.h(776) : error C2248: 'CObject::operator =' : cannot access private member declared in class 'CObject'
1> e:program filesmicrosoft visual studio 9.0vcatlmfcincludeafx.h(562) : see declaration of 'CObject::operator ='
1> e:program filesmicrosoft visual studio 9.0vcatlmfcincludeafx.h(532) : see declaration of 'CObject'
1> This diagnostic occurred in the compiler generated function 'CList<TYPE,ARG_TYPE> &CList<TYPE,ARG_TYPE>::operator =(const CList<TYPE,ARG_TYPE> &)'
1> with
1> [
1> TYPE=CProgram,
1> ARG_TYPE=CProgram &
1> ]
上面這段編譯器報警是否是有似曾相識的感受?想必不少人在用VC2005以及以後的版本的VC編譯器時看到過這個東西,在google查一下error C2248: 'CObject::operator =' : cannot access private member declared in class 'CObject'你會發現不少人碰到相似的問題。一位叫「中國民工」的blog中說明了引起這一問題的的緣由,請參見http://www.cppblog.com/hlong/archive/2007/11/20/37015.html
根據民工兄的解釋,因爲咱們的類中定義了CArray類型的成員,而CArray<A, A&>類的operator=是private類型(它繼承自CObject::operator=,且被定義爲private類型)。並給出瞭解決之道:若是咱們的類/結構體中有CArray(或CList等其餘的派生自CObject類)的成員變量,咱們最好添加上一個public類型的operator=運算賦重載函數;
問題雖然是解決了,可是彷佛仍是沒弄明白產生問題的根本緣由:既然問題是因爲CArray沒有定義Operator=操做從而致使須要調用基類CObject中的私有Operator= 操做而引發的,那麼爲何微軟要將CObject的Operator=操做定義成私有呢?或者說爲何CObject在實際上並無對Operator= 和拷貝構造函數作任何實質性的定義的狀況下要去定義這兩個函數,而且還將他們定義爲private。。惟一的解釋就是微軟不但願繼承自CObject的類 使用默認的Operator=操做,或者說微軟不但願使用了CArray或者CList或者CMap的Collections模板類的類使用默認的Operator=操做。答案的確是如此,不只如此,對於默認的拷貝構造函數結論也是同樣(可能有些人碰到到一樣的編譯器報錯,不過是針對拷貝構造函數的,後面我會解釋引起這兩種類型的報錯的真正緣由)。
要想搞清楚這個問 題,就先要了解C++編譯器生成的默認函數——這些咱們平時一直在使用卻不多關心的幕後工做者究竟是怎樣工做的。當咱們建立一個C++變量,爲一個變量賦 值,或者調用一個C++函數,或者對一個C++變量進行取地址&操做時,這些都是一些基本操做,咱們老是能獲得咱們想要的結果(至少看起來是這 樣)由於這些都是C++的語義,而負責實現這些語義的是C++編譯器。
編譯器又是如何實 現這些語義的呢,好比當你構造一個C++變量時,編譯器會檢查你有沒有爲這個變量的類型建立一個構造函數,若是沒有,編譯器會本身幫你生成一個默認的構造 函數,從而實現了一個C++變量的構造;相似的,在用戶執行其餘一些諸如賦值操做,拷貝構造,取地址等基本操做時,編譯器遵循一樣的原則,即在用戶未定義 相應的操做狀況下自動生成一個默認的操做;正由於如此,甚至不少程序員並不知道它們的存在(我記得幾年前我去一家公司面試的時候,就被問及過這樣一個問題:C++類的默認函數有幾個,分別是什麼,,其實這是一個蠻深入的問題),即便知道它們,也會以爲在不須要咱們付出任何關心的狀況下,這些操做都是理所應當應該是正確的,可是事實並不是老是如此。
Effective C++在條款45也對這幾個函數進行了比較詳細的分析;其中構造函數和析構函數其實就是一個空函數,什麼也不作,因此當咱們用VC也好或者其餘的C++編 譯器建立一個空類也好,編譯器都會爲咱們的類事先定義一個構造和析構函數,就是爲了避免讓咱們去使用默認的構造和析構函數。因此通常狀況下咱們不多會忽視這 兩個函數的存在,可是另外3個很重要的函數:拷貝構造和賦值操做符,以及取地址操做符就很容易被忽視掉,由於咱們不多去實現這3個操做,大部分都是使用的 編譯器提供的默認的實現。
對於默認賦值操做符和拷貝構造函數的默認實現,Effective C++上的解釋是:官 方的規則是:缺省拷貝構造函數(賦值運算符)對類的非靜態數據成員進行 "以成員爲單位的" 逐一拷貝構造(賦值)。即,若是m是類C中類型爲T的非靜態數據成員,而且C沒有聲明拷貝構造函數(賦值運算符),m將會經過類型T的拷貝構造函數(賦值 運算符)被拷貝構造(賦值)---- 若是T有拷貝構造函數(賦值運算符)的話。若是沒有,規則遞歸應用到m的數據成員,直至找到一個拷貝構造函數(賦值運算符)或固定類型(例 如,int,double,指針,等)爲止。默認狀況下,固定類型的對象拷貝構造(賦值)時是從源對象到目標對象的 "逐位" 拷貝。對於從別的類繼承而來的類來講,這條規則適用於繼承層次結構中的每一層,因此,用戶自定義的構造函數和賦值運算符不管在哪一層被聲明,都會被調用。
另一個很重要的概念是:當且僅當相應的操做被定義時,編譯器才爲操做變量所屬的類型生成對應的默認操做;也就是說,若是代碼中沒有出現相應的操做,編譯器什麼也不會作。
再回到咱們一開始民工兄的例子中,假設咱們的類C中定義了一個CArray類型的成員變量,而且C中沒有顯示的定義operator=操做(這就意味着編譯器可能須要爲C自動生成一個默認的operator=操做)根據上面的說法,當且僅當C的實例被賦值時編譯器纔會生 成默認的operator=操做,而編譯器報警告訴咱們,編譯器在生成operator=操做時遇到了障礙,這個障礙就是:C的CArray成員具備一個 賦值運算符定義,可是該定義是私有的(其實是CArray繼承自CObject的operator=定義)。。咱們看一下民工兄的例子的源碼:
3struct A
4{
5 int a;
6};
7
8struct B
9{
10 CArray<A, A&> b;
24};
25
26 typedef CArray<B, B&> C;
27
28void test()
29{
30 B b;
31 C c;
32 c.Add(b);
33 }
從這段代碼中能夠看出,test中對B的實例b並無作任何賦值的操做,爲何編譯器會去實現B的默認operator=操做呢?
問題就處在CArray::Add()的函數簽名身上,Add函數的源碼以下
template<class TYPE, class ARG_TYPE>
AFX_INLINE INT_PTR CArray<TYPE, ARG_TYPE>::Add(ARG_TYPE newElement)
{ INT_PTR nIndex = m_nSize;
SetAtGrow(nIndex, newElement);
return nIndex; }
可見,形參newElement的類型是ARG_TYPE,ARG_TYPE其實就是TYPE的引用,在這裏就是B的引用;答案彷佛明瞭了:
由於Add函數的簽名要求輸入參數的類型爲B&,因此當編譯器編譯語句:c.Add(b); 時會自動將b強制轉換成B的引用,即將這條語句編譯成:B& d = b; c.Add(d); 賦值操做就這樣出現了!
爲了驗證這個想法,能夠作另外一個測試,調用一個傳值的函數,這樣就不須要作「B& d = b;」的轉換了,那麼就應該不會有問題了。
很不幸,實際上編譯器會報一樣的錯誤,只是如今不是operator=而是拷貝構造函數。
原 因很簡單,由於對於傳值的方式,實際上就是「經過值來傳遞一個對象」,而這又是由這個對象的類的拷貝構造函數定義的。也就是說當經過傳值的方式調用一個子 程序時,最終是編譯器經過調用拷貝構造函數來實現的。因此問題是同樣的,由於類型B沒有定義本身的拷貝構造函數,因而編譯器試圖生成一個默認的,但它一樣 遇到了障礙,由於CArray的拷貝構造也是private的(一樣繼承於CObject)。
至此,咱們對於這個問題有了一個比較全面的認識,其實問題的本質在於:不管是默認的operator=仍是默認的拷貝構造也好都是有其致命的缺陷的,正如Effective C++條款11中所描述的,當這些默認的實如今遇到須要動態分配內存的類的時候就會出現問題,也就是所謂的深拷貝問題。而Collections模板類就是典型的不能使用默認operator=和默認的拷貝構造的例子。
因此當咱們自定義的類中包含Collections模板類的成員時咱們就無法再偷懶使用編譯器自動生成的operator=和的拷貝構造了,而必須本身動手實現,這也是微軟想提醒咱們的一個事實。
在windows console下編譯 的時候遇到這個問題的
using namespace std;
#include <iostream>
using namespace std;