運行文件的小技巧:包含2個.CPP和一個.H文件,必須一個.CPP一個.H一一對應。且C++中,只能運行一個項目,要想在多個文件中(.cpp)運行一個.cpp必須建立多個項目,或者將不允許運行的文件從該項目中剔除掉,注意不是刪除。
每一個c++項目中可以包含多個cpp文件和.h文件,不過只能有而且必須有一個cpp文件中包含main函數,否則就會報錯。所以在一個c++項目中不能單獨運行一個cpp文件,只能運行一個項目。如果你想一個一個的運行cpp文件,請建立多個項目,或者在項目中排除上一個包含main函數的文件(在vc6.0和vs2008/vs2010中的方法是右擊文件——在項目中排除,這個操作不會刪除文件,只是從當前項目中排除該文件。),添加下一個包含main函數的文件。
記住即可。對於其他文件中的全局變量,可能需要加extern ?
以下是別人的解答部分:
授人以魚,不如授人以漁.建議樓主好好看看<<C++ primer>>這本書,目前有中文第四版,我非常喜歡它,我也是去年十月份開始學習C++的,看完它再看<<effective C++>>和<<more effective C++>> , 尤其是<<effective C++>>,簡直是C++的聖經,非看不可...最后到高級了.你還可以看看<<深入探索C++對象模型>>...我全看完了,感覺受益匪淺.
解答問題之前,復習一下基本概念;
1:C++中的全局變量,在整個程序中只能定義一次,但可以聲明多次(不限次數); 在一個地方定義,,然后在其他地方使用時,要先聲明一下;
2:什么叫變量定義? 比如 int i; 這就是定義;
而 extern int i; 則 只是聲明;
但如果寫作 extern int i = 0; 則這也是定義,不是聲明;(是不是有點繞??熟悉了就很簡單了)
所以,我覺得你的問題.實際上是源自你對C++語法中變量的定義和聲明這兩個概念的模糊;
你說你在a.cpp 中聲明 i, 而在b.cpp中必須用extern 聲明才可通過編譯,這是正常的..因為你的i是在a.cpp中定義的..
你說你在b.cpp中聲明i, a.cpp中是否使用extern都可以通過編譯,這個問題嘛.我估計你的代碼實際上仍然是在a.cpp中定義了i,而b.cpp中定義的i不是全局的.
至於你說如果有多個源文件.那么編譯順序如何確定.這個問題很難回答你,恐怕不同的編譯器對此的處理都不大相同..我覺得你不應該考慮這個問題..實際上編譯器會把不同的源文件分別、單獨地編譯成獨立的模塊,最后再鏈接成一個可執行程序,因為它們都是獨立編譯的模塊,理論上說.編譯順序是不重要的.
我覺得倒是應該告訴你如何正確地管理和使用全局變量;
首先,建立一個 "global.h"(文件名隨你,我這里舉個例子而已,記得在頭文件里加上頭文件保護符哦!如果你告訴我你不知道什么是頭文件保護符,我強烈建議你不要再往下看了..立刻去買一本C++primer吧);
在global.h文件中.聲明你所需要的所有全局變量,以下是 global.h的內容:
#ifndefGLOBAL_H
#define GLOBAL_H
extern int g_i; // 此處是聲明,另外,在全局變量前加一個 g_ 是好習慣.
#endif
然后新建一個 global.cpp文件,包含 global.h文件,接着,定義所有的全局變量,
以下是global.cpp的內容:
#include "global.h"
int g_i = 1982; // 此處是定義!!!
至此,一切搞定,最后,在你需要用到全局變量的cpp文件中包含 global.h吧...比如你的a.cpp和b.cpp; 編譯順利了吧?
/////////////////////////////////////////////
看到樓主的新問題了..我再補充回答一下.
問題1:我的疑問是,如果在my.cpp中定義了theApp,則必須在mfc.cpp中用extern聲明theApp,否則編譯出錯;但是如果在mfc.cpp中定義theApp,則不必在my.cpp中聲明,編譯也能夠通過,這是為什么呢?
我的回答: 這個問題還是聲明和定義的問題.我之前說過了.一個變量(比如你的這個theApp),在整個程序中只能定義一次, 然后在需要使用它的地方,要先聲明后使用.
因此,看看實際情況:你在my.cpp中定義了theApp,當你在mfc.cpp中要使用它,當然要先聲明它咯,而聲明變量必須加上extern,不然就變成定義了,那么就會導致你在my.cpp和mfc.cpp中定義同名全局變量兩次,自然就無法通過編譯.
而如果你在mfc.cpp中定義theApp的話,因為在my.cpp中沒有直接用到 theApp.所以,就不需要聲明了.這下清楚了吧?呵呵.
還有,補充一個基礎知識,,我們通常寫 int i; 這樣的語句是"定義","定義"實際上就起到了"聲明"的作用; 所以,如果你不是定義變量,而是單純要聲明一個外部的全局變量(也就是其他cpp文件里的全局變量)的時候,是肯定要加extern的.
我覺得樓主是對 與要加extern感到詫異.
問題2:
這個程序我運行的結果是只有構造函數的那些輸出語句執行了,而析構函數的那些輸出語句並沒有執行,這又是為什么呢?
這個講起來有點多.涉及到一個C++程序的啟動過程:我簡單地說說,
以windows為例,點擊一個exe程序后,系統創建一個"進程內核對象",創建4G虛擬內存空間以及其他的一些執行程序需要的資源,然后創建"線程內核對象",啟動一個線程(也就是主線程了),這個線程調用一個 C++ startup函數,該函數會初始化 你的程序中的所有全局變量,( 這個時候你就看到你 theApp的那些基類的構造函數的執行,並打印出來),所有全局變量構造好以后,才開始執行你寫的main函數.
然后,你的main函數 return了.這時,執行一個C++執行期函數exit(),析構你的所有全局變量(也就是theApp), 但這個時候你的console窗口已經退出了.所以你看不到那些析構函數執行時的打印信息了.呵呵.
另外:我真的非常推薦樓主先好好看看<<C++ primer>>和<<effective C++>>這兩本書,不要把<<深入淺出mfc>>當成C++教材來看,雖然這本書很好,並且通過mfc,很好地示范了C++ 繼承,虛函數的妙用.但是,<深入淺出mfc>的作者侯捷說的好:勿於浮沙築高台.. 基礎打牢非常關鍵. 當你把C++的基礎知識搞清以后,再看深入淺出 mfc 其實是很簡單的..
簡單點就是說,.H文件是連接多個.cpp的橋梁或者紐帶。當然對於多個.cpp文件,想要用同一個變量,需要用到extern來聲明。
注意區別聲明與定義。
注意:
何為聲明,何為定義,一定要區別開來。那我們該如何管理這個全局變量呢,包括一些個方法。其實從本質上來講,這個和類都一樣,類也有聲明與定義的區別。
比如,我們一般在.h文件中進行變量(實例變量)和方法(函數的聲明),然后再.C文件中實現(包括定義 ,主要是定義),但不一定是初始化。其實,定義我覺得會有一個默認的初始值。
我們一般的做法是:定義一個globle的.h文件與.cpp文件,然后將聲明全部寫到.h文件中去。將實現或者說是定義寫到.cpp文件中去。
示例如下:
注意在globle.h文件中要加上 #ifndef GLOBLE_H #define GLOBLE_H xxxxxxx #endif
#ifndef GLOBLE_H #define GLOBLE_H #include<iostream> #include"tinyxml.h" #include<string> #include<sstream> #include<math.h> #include<fstream>//文件操作 #include<Windows.h> #include<ctime> #include<winsock.h> #include<math.h> #include"comm.cpp" #include"rasterization.h" using namespace std; extern double car_length; extern const UINT SLEEP_TIME_INTERVAL; //當串口無數據時,sleep至下次查詢間隔的時間,單位:毫秒 extern int realnum; extern int lastnum; extern _sync_com hCom; extern HANDLE hThreadEvent; //時間線程句柄 extern SYSTEMTIME sysTime; //系統當前時間 extern string dataFile; //數據文件名 extern int infoIndex; extern ofstream ocout; extern stringstream dataStream; extern int in; extern int file_length; extern double lon,lat;//經度、緯度 extern double dv,bv,tv;//東向、北向、天向速度 extern short speed;//速度:單位cm/s //extern coordinate COORDINATE; //extern point1 POINT1; 沒有這種寫法, 這是完全錯誤的,這是啥,聲明套聲明嗎? 我們直接定義變量即可。還有就是下面的是聲明,所謂extern 它就是為了聲明一些個變量而存在的,至於
結構體這種自定義類型的變量,聲明用typedef更好些,不過用extern是完全可以的,可以到網上看看。但是我們在.h中聲明了,就不要在去.cpp中聲明了,重復工作,不足取。
//extern line LINE; //extern roadnet ROADNET; //extern trackpoint TRACKPOINT; typedef struct coordinate { }COORDINATE; typedef struct point1 { }POINT1; //普通線 typedef struct line { }LINE; //路網 typedef struct roadnet {
}ROADNET; //路點對象,代表kml里Point類型的Placemark typedef struct trackpoint { }TRACKPOINT; extern bool matchFalse; extern ROADNET* roadnet; extern TRACKPOINT **trackpoints; extern int trackpointsnumber; extern double azimuth; double distBetweenPoints(double latA, double lonA, double latB, double lonB); #endif
globle.cpp 當中文件
#include"globle.h" double car_length=4; const UINT SLEEP_TIME_INTERVAL = 0; //當串口無數據時,sleep至下次查詢間隔的時間,單位:毫秒 int realnum = 0; int lastnum=-1; _sync_com hCom; HANDLE hThreadEvent; //時間線程句柄 SYSTEMTIME sysTime; //系統當前時間 string dataFile = ""; //數據文件名 int infoIndex = 1; ofstream ocout; stringstream dataStream; int in = 0; int file_length; double lon,lat;//經度、緯度 double dv,bv,tv;//東向、北向、天向速度 short speed;//速度:單位cm/s bool matchFalse = false; ROADNET* roadnet = NULL; TRACKPOINT **trackpoints; int trackpointsnumber = 0; double azimuth = -3.1415926/2; /* * 計算兩個經緯度坐標之間的距離,公式為: * MLatA A的緯度,MLonA A的經度,MlatB B的緯度,MlonB B的經度 * C = sin(MLatA)*sin(MLatB)*cos(MLonA-MLonB) + cos(MLatA)*cos(MLatB) * Distance = R*Arccos(C)*Pi/180 * @param latA A點緯度 * @param lonA A點經度 * @param latB B點緯度 * @param lonB B點經度 * return 返回距離值 */ double distBetweenPoints(double latA, double lonA, double latB, double lonB) { if (latA==latB && lonA == lonB) return 0; //定義pi const double PI = 3.1415926535897932384626433832795; //定義地球半徑,單位為米 const double R = 6371004; //公式 double C = sin(latA) * sin(latB) * cos(lonA - lonB) + cos(latA) * cos(latB); double distance = R * acos(C) * PI / 180; return distance; }