一、C++概述
(一) 發(fā)展歷史
1980年,Bjarne Stroustrup博士開始著手創(chuàng)建一種模擬語言,能夠具有面向?qū)ο蟮某绦蛟O(shè)計特色。在當(dāng)時,面向?qū)ο缶幊踢€是一個比較新的理念,Stroustrup博士并不是從頭開始設(shè)計新語言,而是在C語言的基礎(chǔ)上進行創(chuàng)建。這就是C++語言。
1985年,C++開始在外面慢慢流行。經(jīng)過多年的發(fā)展,C++已經(jīng)有了多個版本。為次,ANSI和ISO的聯(lián)合委員會于1989年著手為C++制定標(biāo)準(zhǔn)。1994年2月,該委員會出版了第一份非正式草案,1998年正式推出了C++的國際標(biāo)準(zhǔn)。
(二) C和C++
C++是C的超集,也可以說C是C++的子集,因為C先出現(xiàn)。按常理說,C++編譯器能夠編譯任何C程序,但是C和C++還是有一些小差別。
例如C++增加了C不具有的關(guān)鍵字。這些關(guān)鍵字能作為函數(shù)和變量的標(biāo)識符在C程序中使用,盡管C++包含了所有的C,但顯然沒有任何C++編譯器能編譯這樣的C程序。
C程序員可以省略函數(shù)原型,而C++不可以,一個不帶參數(shù)的C函數(shù)原型必須把void寫出來。而C++可以使用空參數(shù)列表。
C++中new和delete是對內(nèi)存分配的運算符,取代了C中的malloc和free。
標(biāo)準(zhǔn)C++中的字符串類取代了C標(biāo)準(zhǔn)C函數(shù)庫頭文件中的字符數(shù)組處理函數(shù)。
C++中用來做控制態(tài)輸入輸出的iostream類庫替代了標(biāo)準(zhǔn)C中的stdio函數(shù)庫。
C++中的try/catch/throw異常處理機制取代了標(biāo)準(zhǔn)C中的setjmp()和longjmp()函數(shù)。
二、關(guān)鍵字和變量
C++相對與C增加了一些關(guān)鍵字,如下:
typename bool dynamic_cast mutable namespace
static_cast using catch explicit new
virtual operator false private template
volatile const protected this wchar_t
const_cast public throw friend true
reinterpret_cast try
bitor xor_e and_eq compl or_eq
not_eq bitand
在C++中還增加了bool型變量和wchar_t型變量:
布爾型變量是有兩種邏輯狀態(tài)的變量,它包含兩個值:真和假。如果在表達(dá)式中使用了布爾型變量,那么將根據(jù)變量值的真假而賦予整型值1或0。要把一個整型變量轉(zhuǎn)換成布爾型變量,如果整型值為0,則其布爾型值為假;反之如果整型值為非0,則其布爾型值為真。布兒型變量在運行時通常用做標(biāo)志,比如進行邏輯測試以改變程序流程。
#include iostream.h
int main()
{
bool flag;
flag=true;
if(flag) cout < return 0;
}
C++中還包括wchar_t數(shù)據(jù)類型,wchar_t也是字符類型,但是是那些寬度超過8位的數(shù)據(jù)類型。許多外文字符集所含的數(shù)目超過256個,char字符類型無法完全囊括。wchar_t數(shù)據(jù)類型一般為16位。
標(biāo)準(zhǔn)C++的iostream類庫中包括了可以支持寬字符的類和對象。用wout替代cout即可。
#include iostream.h
int main()
{
wchar_t wc;
wc='b';
wout < wc='y';
wout < wc='e';
wout < return 0;
}
說明一下:某些編譯器無法編譯該程序(不支持該數(shù)據(jù)類型)。
三、強制類型轉(zhuǎn)換 有時候,根據(jù)表達(dá)式的需要,某個數(shù)據(jù)需要被當(dāng)成另外的數(shù)據(jù)類型來處理,這時,就需要強制編譯器把變量或常數(shù)由聲明時的類型轉(zhuǎn)換成需要的類型。為此,就要使用強制類型轉(zhuǎn)換說明,格式如下: int* iptr=(int*) &table; 表達(dá)式的前綴(int*)就是傳統(tǒng)C風(fēng)格的強制類型轉(zhuǎn)換說明(typecast),又可稱為強制轉(zhuǎn)換說明(cast)。強制轉(zhuǎn)換說明告訴編譯器把表達(dá)式轉(zhuǎn)換成指定的類型。有些情況下強制轉(zhuǎn)換是禁用的,例如不能把一個結(jié)構(gòu)類型轉(zhuǎn)換成其他任何類型。數(shù)字類型和數(shù)字類型、指針和指針之間可以相互轉(zhuǎn)換。當(dāng)然,數(shù)字類型和指針類型也可以相互轉(zhuǎn)換,但通常認(rèn)為這樣做是不安全而且也是沒必要的。強制類型轉(zhuǎn)換可以避免編譯器的警告。 long int el=123; short i=(int) el; float m=34.56; int i=(int) m; 上面兩個都是C風(fēng)格的強制類型轉(zhuǎn)換,C++還增加了一種轉(zhuǎn)換方式,比較一下上面和下面這個書寫方式的不同: long int el=123; short i=int (el); float m=34.56; int i=int (m); 使用強制類型轉(zhuǎn)換的好處就是:禁止編譯器對你故意去做的事發(fā)出警告。但是,利用強制類型轉(zhuǎn)換說明使得編譯器的類型檢查機制失效,這不是明智的選擇。通常,是不提倡進行強制類型轉(zhuǎn)換的。除非不可避免,如要調(diào)用malloc()函數(shù)時要用的void型指針轉(zhuǎn)換成指定類型指針。 四、標(biāo)準(zhǔn)輸入輸出流 在C語言中,輸入輸出是使用語句scanf()和printf()來實現(xiàn)的,而C++中是使用類來實現(xiàn)的。 #include iostream.h main() //C++中main()函數(shù)默認(rèn)為int型,而C語言中默認(rèn)為void型。 { int a; cout < cin>>a; /*輸入一個數(shù)值*/ cout < return 0; } cin,cout,endl對象,他們本身并不是C++語言的組成部分。雖然他們已經(jīng)是ANSI標(biāo)準(zhǔn)C++中被定義,但是他們不是語言的內(nèi)在組成部分。在C++中不提供內(nèi)在的輸入輸出運算符,這與其他語言是不同的。輸入和輸出是通過C++類來實現(xiàn)的,cin和cout是這些類的實例,他們是在C++語言的外部實現(xiàn)。 在C++語言中,有了一種新的注釋方法,就是‘//’,在該行//后的所有說明都被編譯器認(rèn)為是注釋,這種注釋不能換行。C++中仍然保留了傳統(tǒng)C語言的注釋風(fēng)格/*……*/。 C++也可采用格式化輸出的方法: #include iostream.h int main() { int a; cout < cin>>a; cout
五、函數(shù)重載 在C++中,允許有相同的函數(shù)名,不過它們的參數(shù)類型不能完全相同,這樣這些函數(shù)就可以相互區(qū)別開來。而這在C語言中是不允許的。 1.參數(shù)個數(shù)不同 #include iostream.h void a(int,int); void a(int); int main() { a(5); a(6,7); return 0; } void a(int i) { cout < } void a(int i,int j) { cout < } 2.參數(shù)格式不同 #include iostream.h void a(int,int); void a(int,float); int main() { a(5,6); a(6,7.0); return 0; } void a(int i,int j) { cout < } void a(int i,float j) { cout < } 六、變量作用域 C++語言中,允許變量定義語句在程序中的任何地方,只要在是使用它之前就可以;而C語言中,必須要在函數(shù)開頭部分。而且C++允許重復(fù)定義變量,C語言也是做不到這一點的。看下面的程序: #include iostream.h int a; int main() { cin >>a; for(int i=1;i <=10;i++) //C語言中,不允許在這里定義變量 { static int a=0; //C語言中,同一函數(shù)塊,不允許有同名變量 a+=i; cout <<::a<< < } return 0; }
七、new和delete運算符 在C++語言中,仍然支持malloc()和free()來分配和釋放內(nèi)存,同時增加了new和delete來管理內(nèi)存。 1.為固定大小的數(shù)組分配內(nèi)存 #include iostream.h int main() { int *birthday=new int[3]; birthday[0]=6; birthday[1]=24; birthday[2]=1940; cout < < delete [] birthday; //注意這兒 return 0; } 在刪除數(shù)組時,delete運算符后要有一對方括號。 2.為動態(tài)數(shù)組分配內(nèi)存 #include iostream.h #include stdlib.h int main() { int size; cin >>size; int *array=new int[size]; for(int i=0;i array[i]=rand(); for(i=0;i cout <<'\n'< delete [] array; return 0; } 八、引用型變量 在C++中,引用是一個經(jīng)常使用的概念。引用型變量是其他變量的一個別名,我們可以認(rèn)為他們只是名字不相同,其他都是相同的。 1.引用是一個別名 C++中的引用是其他變量的別名。聲明一個引用型變量,需要給他一個初始化值,在變量的生存周期內(nèi),該值不會改變。 & 運算符定義了一個引用型變量: int a; int & b=a; 先聲明一個名為a的變量,它還有一個別名b。我們可以認(rèn)為是一個人,有一個真名,一個外號,以后不管是喊他a還是b,都是叫他這個人。同樣,作為變量,以后對這兩個標(biāo)識符操作都會產(chǎn)生相同的效果。 #include iostream.h int main() { int a=123; int & b=a; cout < a++; cout < b++; cout < return 0; } 2.引用的初始化 和指針不同,引用變量的值不可改變。引用作為真實對象的別名,必須進行初始化,除非滿足下列條件之一: (1) 引用變量被聲明為外部的,它可以在任何地方初始化 (2) 引用變量作為類的成員,在構(gòu)造函數(shù)里對它進行初始化 (3) 引用變量作為函數(shù)聲明的形參,在函數(shù)調(diào)用時,用調(diào)用者的實參來進行初始化 3.作為函數(shù)形參的引用 引用常常被用作函數(shù)的形參。以引用代替拷貝作為形參的優(yōu)點: 引用避免了傳遞大型數(shù)據(jù)結(jié)構(gòu)帶來的額外開銷 引用無須象指針那樣需要使用*和- >等運算符 #include iostream.h void func1(s p); void func2(s & p); struct s { int n; char text[10]; }; int main() { static s str={123,China}; func1(str); func2(str); return 0; } void func1(s p) { cout < cout< } void func2(s & p) { cout < cout< } 從表面上看,這兩個函數(shù)沒有明顯區(qū)別,不過他們所花的時間卻有很大差異,func2()函數(shù)所用的時間開銷會比func2()函數(shù)少很多。它們還有一個差別,如果程序遞歸func1(),隨著遞歸的深入,會因為棧的耗盡而崩潰,但func2()沒有這樣的擔(dān)憂。 4.以引用方式調(diào)用 當(dāng)函數(shù)把引用作為參數(shù)傳遞給另一個函數(shù)時,被調(diào)用函數(shù)將直接對參數(shù)在調(diào)用者中的拷貝進行操作,而不是產(chǎn)生一個局部的拷貝(傳遞變量本身是這樣的)。這就稱為以引用方式調(diào)用。把參數(shù)的值傳遞到被調(diào)用函數(shù)內(nèi)部的拷貝中則稱為以傳值方式調(diào)用。 #include iostream.h void display(const Date &,const char*); void swapper(Date &,Date&); struct Date { int month,day,year; }; int main() { static Date now={2,23,90}; static Date then={9,10,60}; display(now,Now: ); display(then,Then: ); swapper(now,then); display(now,Now: ); display(then,Then: ); return 0; } void swapper(Date & dt1,Date& dt2) { Date save; save=dt1; dt1=dt2; dt2=save; } void display(const Date & dt,const char *s) { cout < cout< } 5.以引用作為返回值 #include iostream.h struct Date { int month,day,year; }; Date birthdays[]= { {12,12,60}; {10,25,85}; {5,20,73}; }; const Date & getdate(int n) { return birthdays[n-1]; } int main() { int dt=1; while(dt!=0) { cout < cin>>dt; if(dt >0 && dt<4) { const Date & bd=getdate(dt); cout < } } return 0; } 程序都很簡單,就不講解了
三、強制類型轉(zhuǎn)換 有時候,根據(jù)表達(dá)式的需要,某個數(shù)據(jù)需要被當(dāng)成另外的數(shù)據(jù)類型來處理,這時,就需要強制編譯器把變量或常數(shù)由聲明時的類型轉(zhuǎn)換成需要的類型。為此,就要使用強制類型轉(zhuǎn)換說明,格式如下: int* iptr=(int*) &table; 表達(dá)式的前綴(int*)就是傳統(tǒng)C風(fēng)格的強制類型轉(zhuǎn)換說明(typecast),又可稱為強制轉(zhuǎn)換說明(cast)。強制轉(zhuǎn)換說明告訴編譯器把表達(dá)式轉(zhuǎn)換成指定的類型。有些情況下強制轉(zhuǎn)換是禁用的,例如不能把一個結(jié)構(gòu)類型轉(zhuǎn)換成其他任何類型。數(shù)字類型和數(shù)字類型、指針和指針之間可以相互轉(zhuǎn)換。當(dāng)然,數(shù)字類型和指針類型也可以相互轉(zhuǎn)換,但通常認(rèn)為這樣做是不安全而且也是沒必要的。強制類型轉(zhuǎn)換可以避免編譯器的警告。 long int el=123; short i=(int) el; float m=34.56; int i=(int) m; 上面兩個都是C風(fēng)格的強制類型轉(zhuǎn)換,C++還增加了一種轉(zhuǎn)換方式,比較一下上面和下面這個書寫方式的不同: long int el=123; short i=int (el); float m=34.56; int i=int (m); 使用強制類型轉(zhuǎn)換的好處就是:禁止編譯器對你故意去做的事發(fā)出警告。但是,利用強制類型轉(zhuǎn)換說明使得編譯器的類型檢查機制失效,這不是明智的選擇。通常,是不提倡進行強制類型轉(zhuǎn)換的。除非不可避免,如要調(diào)用malloc()函數(shù)時要用的void型指針轉(zhuǎn)換成指定類型指針。 四、標(biāo)準(zhǔn)輸入輸出流 在C語言中,輸入輸出是使用語句scanf()和printf()來實現(xiàn)的,而C++中是使用類來實現(xiàn)的。 #include iostream.h main() //C++中main()函數(shù)默認(rèn)為int型,而C語言中默認(rèn)為void型。 { int a; cout < cin>>a; /*輸入一個數(shù)值*/ cout < return 0; } cin,cout,endl對象,他們本身并不是C++語言的組成部分。雖然他們已經(jīng)是ANSI標(biāo)準(zhǔn)C++中被定義,但是他們不是語言的內(nèi)在組成部分。在C++中不提供內(nèi)在的輸入輸出運算符,這與其他語言是不同的。輸入和輸出是通過C++類來實現(xiàn)的,cin和cout是這些類的實例,他們是在C++語言的外部實現(xiàn)。 在C++語言中,有了一種新的注釋方法,就是‘//’,在該行//后的所有說明都被編譯器認(rèn)為是注釋,這種注釋不能換行。C++中仍然保留了傳統(tǒng)C語言的注釋風(fēng)格/*……*/。 C++也可采用格式化輸出的方法: #include iostream.h int main() { int a; cout < cin>>a; cout
五、函數(shù)重載 在C++中,允許有相同的函數(shù)名,不過它們的參數(shù)類型不能完全相同,這樣這些函數(shù)就可以相互區(qū)別開來。而這在C語言中是不允許的。 1.參數(shù)個數(shù)不同 #include iostream.h void a(int,int); void a(int); int main() { a(5); a(6,7); return 0; } void a(int i) { cout < } void a(int i,int j) { cout < } 2.參數(shù)格式不同 #include iostream.h void a(int,int); void a(int,float); int main() { a(5,6); a(6,7.0); return 0; } void a(int i,int j) { cout < } void a(int i,float j) { cout < } 六、變量作用域 C++語言中,允許變量定義語句在程序中的任何地方,只要在是使用它之前就可以;而C語言中,必須要在函數(shù)開頭部分。而且C++允許重復(fù)定義變量,C語言也是做不到這一點的。看下面的程序: #include iostream.h int a; int main() { cin >>a; for(int i=1;i <=10;i++) //C語言中,不允許在這里定義變量 { static int a=0; //C語言中,同一函數(shù)塊,不允許有同名變量 a+=i; cout <<::a<< < } return 0; }
七、new和delete運算符 在C++語言中,仍然支持malloc()和free()來分配和釋放內(nèi)存,同時增加了new和delete來管理內(nèi)存。 1.為固定大小的數(shù)組分配內(nèi)存 #include iostream.h int main() { int *birthday=new int[3]; birthday[0]=6; birthday[1]=24; birthday[2]=1940; cout < < delete [] birthday; //注意這兒 return 0; } 在刪除數(shù)組時,delete運算符后要有一對方括號。 2.為動態(tài)數(shù)組分配內(nèi)存 #include iostream.h #include stdlib.h int main() { int size; cin >>size; int *array=new int[size]; for(int i=0;i array[i]=rand(); for(i=0;i cout <<'\n'< delete [] array; return 0; } 八、引用型變量 在C++中,引用是一個經(jīng)常使用的概念。引用型變量是其他變量的一個別名,我們可以認(rèn)為他們只是名字不相同,其他都是相同的。 1.引用是一個別名 C++中的引用是其他變量的別名。聲明一個引用型變量,需要給他一個初始化值,在變量的生存周期內(nèi),該值不會改變。 & 運算符定義了一個引用型變量: int a; int & b=a; 先聲明一個名為a的變量,它還有一個別名b。我們可以認(rèn)為是一個人,有一個真名,一個外號,以后不管是喊他a還是b,都是叫他這個人。同樣,作為變量,以后對這兩個標(biāo)識符操作都會產(chǎn)生相同的效果。 #include iostream.h int main() { int a=123; int & b=a; cout < a++; cout < b++; cout < return 0; } 2.引用的初始化 和指針不同,引用變量的值不可改變。引用作為真實對象的別名,必須進行初始化,除非滿足下列條件之一: (1) 引用變量被聲明為外部的,它可以在任何地方初始化 (2) 引用變量作為類的成員,在構(gòu)造函數(shù)里對它進行初始化 (3) 引用變量作為函數(shù)聲明的形參,在函數(shù)調(diào)用時,用調(diào)用者的實參來進行初始化 3.作為函數(shù)形參的引用 引用常常被用作函數(shù)的形參。以引用代替拷貝作為形參的優(yōu)點: 引用避免了傳遞大型數(shù)據(jù)結(jié)構(gòu)帶來的額外開銷 引用無須象指針那樣需要使用*和- >等運算符 #include iostream.h void func1(s p); void func2(s & p); struct s { int n; char text[10]; }; int main() { static s str={123,China}; func1(str); func2(str); return 0; } void func1(s p) { cout < cout< } void func2(s & p) { cout < cout< } 從表面上看,這兩個函數(shù)沒有明顯區(qū)別,不過他們所花的時間卻有很大差異,func2()函數(shù)所用的時間開銷會比func2()函數(shù)少很多。它們還有一個差別,如果程序遞歸func1(),隨著遞歸的深入,會因為棧的耗盡而崩潰,但func2()沒有這樣的擔(dān)憂。 4.以引用方式調(diào)用 當(dāng)函數(shù)把引用作為參數(shù)傳遞給另一個函數(shù)時,被調(diào)用函數(shù)將直接對參數(shù)在調(diào)用者中的拷貝進行操作,而不是產(chǎn)生一個局部的拷貝(傳遞變量本身是這樣的)。這就稱為以引用方式調(diào)用。把參數(shù)的值傳遞到被調(diào)用函數(shù)內(nèi)部的拷貝中則稱為以傳值方式調(diào)用。 #include iostream.h void display(const Date &,const char*); void swapper(Date &,Date&); struct Date { int month,day,year; }; int main() { static Date now={2,23,90}; static Date then={9,10,60}; display(now,Now: ); display(then,Then: ); swapper(now,then); display(now,Now: ); display(then,Then: ); return 0; } void swapper(Date & dt1,Date& dt2) { Date save; save=dt1; dt1=dt2; dt2=save; } void display(const Date & dt,const char *s) { cout < cout< } 5.以引用作為返回值 #include iostream.h struct Date { int month,day,year; }; Date birthdays[]= { {12,12,60}; {10,25,85}; {5,20,73}; }; const Date & getdate(int n) { return birthdays[n-1]; } int main() { int dt=1; while(dt!=0) { cout < cin>>dt; if(dt >0 && dt<4) { const Date & bd=getdate(dt); cout < } } return 0; } 程序都很簡單,就不講解了