標籤:style java 使用 檔案 資料 ar 問題 代碼
一、如何用C++的源檔案產生一個可執行程式
一個C++程式由一個或者多個編譯單元組成。每個編譯單元都是一個獨立的原始碼檔案,通常是一個帶.cpp的檔案,編譯器每次編一個檔案編譯單元,產生一個以.obj或者.o為尾碼的目標檔案。程式就是運行在這些目標檔案上。這些目標檔案都是二進位的檔案。一旦所有的編譯單元都產生了目標檔案,我們就用連接器將他們串連成一個可執行檔.exe檔案。
我們可以在一個.cpp檔案中實現多個類,也可以將多個類分散的放在多個.cpp檔案中。當修改了某一個.cpp檔案後,我們只需要重新編譯這個檔案,就可產生新的可執行程式。
通過編譯器,可以將兩個cpp檔案分別編譯產生.o檔案。在通過.o檔案產生可執行程式。例如:
CC -c main.cpp
CC -c test.cpp
CC main.o test.o -o test
最後執行./test 123
在main檔案中調用了test檔案中的函數。在調用前需要聲明test中的函數。如果檔案過多的時候會出現重複聲明的問題,比如A中聲明了B中的函數,C中也聲明了B中的函數,這時候用A調用C時會出現這個函式宣告重複的錯誤,連接器會報錯輸出“unresolved symbol”(不可解析的符號),所以在實際應用中,我們是通過將這個函式宣告寫入標頭檔中,如.h\.hh\.phh\.hxx等,在我們需要調用這個函數的時候,包含這個函數的標頭檔就可以了。格式如下:
#ifndef TEST_H
#define TEST_H
int test(int);
#endif
不要認為程式就是一些目標檔案組成的。實際情況中,可執行程式通常都會串連許多庫,這些庫已經實現了許多現成的功能。庫主要有兩種類型:
l 靜態庫可以直接放入可執行程式中,就像目標檔案一樣,但會使可執行檔變得很大。
l 動態庫DLL位於機器上的標準位置,並且在應用程式啟動的時候自動載入他們。
C++的可編譯性和對效能的追求是不同於Java和C#等語言的。C++不會在運行時檢測數組是否越界,沒有垃圾資訊收集器回收那些分配出去但是不再使用的動態記憶體。
高位元組在後的系統架構(如PowerPC和SPARC),23位變數值0x12345678會儲存為4個位元組:0x12、0x34、0x56、0x78。對於高位元組在前的系統架構(比如Intel x86體系)。這些位元組儲存順序會被顛倒過來。這樣就會把記憶體地區中資料複製到磁碟或者在網路上發送二進位程式中產生差異。
二、C++文法
內斂函數(inline)在類定義中已經實現了方法。與之對應的是把函數原型放在標頭檔中,而把實現這些函數的代碼放在.cpp檔案中。從文法上講這兩種方法是等效的,但是當我們調用內嵌函式時,絕大多數編譯器只是對此函數做簡單的擴充,而不會產生實際的函數調用。這樣會是程式運行效率更高,但是相應的會帶來應用程式的增大。所以,只有非常簡單的函數才實現為內嵌函式。
Virtual fun()=0//純虛函數——沒有預設實現代碼並且必須在子類中實現的函數。
C++中,如果是只想某個執行個體對象的指標要訪問類方法時,必須使用“->”,如果是執行個體則可以用“.”。
New動態分配的對象一般分配在“堆”上,而局部變數(在函數中定義的變數)則儲存在“棧”裡。
將指標定義為const類型,可以限制指標不讓其修改它們,只能用於調用常量成員。
Typedef重新定義資料類型,設定成其他的名字(別名)
C++中的資料類型強制轉換,此文法功能非常強大。可以改變指標類型,移除const等等。
C++中引入4種具有更為準確語義的新強制轉換類型。
1、Static_cast<T>()可用於把指向A的指標強制轉換為指向B的指標,其約束條件是類B必須是類A的子類。
2、Dynamic_cast<T>(),與Static_cast<T>()類似,只是它使用的是運行時類型資訊的方法來驗證與這個指標相關的對象是否是類B的一個執行個體。如果不是,強制轉換就會返回一個null 指標null。
3、Const_cast<T>()添加或移除對指標或者引用的const限定。
4、Reinterpret_cast<T>()把人一類型的指標或者引用轉換成任意的其他類型。
可能有點模糊,我的理解就是Static_cast<T>()這種情況是對那些操作轉換規範不會出問題的轉換用的,Dynamic_cast<T>()則是對那些可能出錯的轉換用的,因為有返回資訊可以查看是否轉換成功,希望有更好的解釋在下面告訴我。其他兩個還算比較清晰。
Static靜態關鍵字的功能是讓被此關鍵字聲明的變數或者函數只能在此編譯單元下用,稱這種情況較靜態串連(static linkage)。其他情況則成為外部串連(external linkage)。
命名空間的使用除了::前面加上這個命名空間名,還有下面三種機制:
定義命名空間的別名
Namespace a = aaaaaaaaaaaaaaaaaaaaaaaaa;
從命名空間中匯入一個簡單的標識符
Using aaaaaaaaaaaaaaaaaaaaaaaaaaa::fun;
fun();
只用一條指令匯入整個命名空間
Using namespace aaaaaaaaaaaaaaaaaa;
前置處理器就是一個程式,可以把帶“#”指令符轉換成不在包含哪些指令符的源檔案。
1、#include指令會把<>和””包含的標頭檔擴充成他們的內容。
2、#define替換成宏定義的內容。
3、#undef解除宏定義。
4、#if、#elif、#else和#endif可以處理或者跳過某部分代碼。
5、#ifdef、#ifndef來避免重複包含某個標頭檔。
6、#error可以在編譯時間給出使用者自訂的錯誤資訊。