首頁技術(shù)文章正文

C++ 與C如何區(qū)分?

更新時(shí)間:2018-11-29 來源:黑馬程序員技術(shù)社區(qū) 瀏覽量:

編程的學(xué)習(xí)學(xué)無止境,只掌握一門語言是遠(yuǎn)遠(yuǎn)不夠的,現(xiàn)在我們開始C++的學(xué)習(xí)之路,下面先看下C++ 與C 的區(qū)別

一、C++概述

1、發(fā)展歷史

      1980年,Bjarne Stroustrup博士開始著手創(chuàng)建一種模擬語言,能夠具有面向?qū)ο蟮某绦蛟O(shè)計(jì)特色。在當(dāng)時(shí),面向?qū)ο缶幊踢€是一個(gè)比較新的理念,Stroustrup博士并不是從頭開始設(shè)計(jì)新語言,而是在C語言的基礎(chǔ)上進(jìn)行創(chuàng)建。這就是C++語言。

     1985年,C++開始在外面慢慢流行。經(jīng)過多年的發(fā)展,C++已經(jīng)有了多個(gè)版本。為次,ANSI和ISO的聯(lián)合委員會(huì)于1989年著手為C++制定標(biāo)準(zhǔn)。1994年2月,該委員會(huì)出版了第一份非正式草案,1998年正式推出了C++的國際標(biāo)準(zhǔn)。

2、C和C++

      C++是C的超集,也可以說C是C++的子集,因?yàn)镃先出現(xiàn)。按常理說,C++編譯器能夠編譯任何C程序,但是C和C++還是有一些小差別。

      例如C++增加了C不具有的關(guān)鍵字。這些關(guān)鍵字能作為函數(shù)和變量的標(biāo)識(shí)符在C程序中使用,盡管C++包含了所有的C,但顯然沒有任何C++編譯器能編譯這樣的C程序。

     C程序員可以省略函數(shù)原型,而C++不可以,一個(gè)不帶參數(shù)的C函數(shù)原型必須把void寫出來。而C++可以使用空參數(shù)列表。

     C++中new和delete是對內(nèi)存分配的運(yùn)算符,取代了C中的malloc和free。

     標(biāo)準(zhǔn)C++中的字符串類取代了C標(biāo)準(zhǔn)C函數(shù)庫頭文件中的字符數(shù)組處理函數(shù)(C中沒有字符串類型)。

     C++中用來做控制態(tài)輸入輸出的iostream類庫替代了標(biāo)準(zhǔn)C中的stdio函數(shù)庫。

     C++中的try/catch/throw異常處理機(jī)制取代了標(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)的變量,它包含兩個(gè)值:真和假。如果在表達(dá)式中使用了布爾型變量,那么將根據(jù)變量值的真假而賦予整型值1或0。要把一個(gè)整型變量轉(zhuǎn)換成布爾型變量,如果整型值為0,則其布爾型值為假;反之如果整型值為非0,則其布爾型值為真。布兒型變量在運(yùn)行時(shí)通常用做標(biāo)志,比如進(jìn)行邏輯測試以改變程序流程。

#include iostream.h

      

int main()

{           

        bool flag;

        flag = true;

        if(flag)

                cout << true << endl;

        return 0;

}

C++中還包括wchar_tt數(shù)據(jù)類型,wchar_t也是字符類型,但是是那些寬度超過8位的數(shù)據(jù)類型。許多外文字符集所含的數(shù)目超過256個(gè),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;

        wc = 'y';

        wout << wc;

        wc = 'e';

        wout << wc << endl;

        return 0;

}

說明一下:某些編譯器無法編譯該程序(不支持該數(shù)據(jù)類型)。

三、強(qiáng)制類型轉(zhuǎn)換

     有時(shí)候,根據(jù)表達(dá)式的需要,某個(gè)數(shù)據(jù)需要被當(dāng)成另外的數(shù)據(jù)類型來處理,這時(shí),就需要強(qiáng)制編譯器把變量或常數(shù)由聲明時(shí)的類型轉(zhuǎn)換成需要的類型。為此,就要使用強(qiáng)制類型轉(zhuǎn)換說明,格式如下:

int* iptr=(int*) &table;

表達(dá)式的前綴(int*)就是傳統(tǒng)C風(fēng)格的強(qiáng)制類型轉(zhuǎn)換說明(typecast),又可稱為強(qiáng)制轉(zhuǎn)換說明(cast)。強(qiáng)制轉(zhuǎn)換說明告訴編譯器把表達(dá)式轉(zhuǎn)換成指定的類型。有些情況下強(qiáng)制轉(zhuǎn)換是禁用的,例如不能把一個(gè)結(jié)構(gòu)類型轉(zhuǎn)換成其他任何類型。數(shù)字類型和數(shù)字類型、指針和指針之間可以相互轉(zhuǎn)換。當(dāng)然,數(shù)字類型和指針類型也可以相互轉(zhuǎn)換,但通常認(rèn)為這樣做是不安全而且也是沒必要的。強(qiáng)制類型轉(zhuǎn)換可以避免編譯器的警告。


long int el = 123;

short i = (int) el;

float m = 34.56;

int i = (int) m;

上面兩個(gè)都是C風(fēng)格的強(qiáng)制類型轉(zhuǎn)換,C++還增加了一種轉(zhuǎn)換方式,比較一下上面和下面這個(gè)書寫方式的不同:

long int el = 123;

short i = int (el);

float m = 34.56;

int i = int (m);


使用強(qiáng)制類型轉(zhuǎn)換的最大好處就是:禁止編譯器對你故意去做的事發(fā)出警告。但是,利用強(qiáng)制類型轉(zhuǎn)換說明使得編譯器的類型檢查機(jī)制失效,這不是明智的選擇。通常,是不提倡進(jìn)行強(qiáng)制類型轉(zhuǎn)換的。除非不可避免,如要調(diào)用malloc()函數(shù)時(shí)要用的void型指針轉(zhuǎn)換成指定類型指針。

四、標(biāo)準(zhǔn)輸入輸出流


       在C語言中,輸入輸出是使用語句scanf()和printf()來實(shí)現(xiàn)的,而C++中是使用類來實(shí)現(xiàn)的。


#include iostream.h

main()    //C++中main()函數(shù)默認(rèn)為int型,而C語言中默認(rèn)為void型。

{

        int a;

        cout << input a number: ;

        cin >> a;             /*輸入一個(gè)數(shù)值*/

        cout << a << endl;      //輸出并回車換行

       

        return 0;

}

    cin,cout,endl對象,他們本身并不是C++語言的組成部分。雖然他們已經(jīng)是ANSI標(biāo)準(zhǔn)C++中被定義,但是他們不是語言的內(nèi)在組成部分。在C++中不提供內(nèi)在的輸入輸出運(yùn)算符,這與其他語言是不同的。輸入和輸出是通過C++類來實(shí)現(xiàn)的,cin和cout是這些類的實(shí)例,他們是在C++語言的外部實(shí)現(xiàn)。


     在C++語言中,有了一種新的注釋方法,就是‘//’,在該行//后的所有說明都被編譯器認(rèn)為是注釋,這種注釋不能換行。C++中仍然保留了傳統(tǒng)C語言的注釋風(fēng)格/*……*/。

C++也可采用格式化輸出的方法:

#include iostream.h

      

int main()

{         

        int a;           

        cout << input a number: ;         

        cin >> a;

           

        cout << dec << a << ' '     //輸出十進(jìn)制數(shù)               

        << oct << a << ' '     //輸出八進(jìn)制數(shù)               

        << hex << a << endl;   //輸出十六進(jìn)制數(shù)

           

        return 0;      

}

從上面也可以看出,dec,oct,hex也不可作為變量的標(biāo)識(shí)符在程序中出現(xiàn)。




五、函數(shù)參數(shù)問題


1、無名的函數(shù)形參


       聲明函數(shù)時(shí)可以包含一個(gè)或多個(gè)用不到的形式參數(shù)。這種情況多出現(xiàn)在用一個(gè)通用的函數(shù)指針調(diào)用多個(gè)函數(shù)的場合,其中有些函數(shù)不需要函數(shù)指針聲明中的所有參數(shù)。看下面的例子:

int fun(int x,int y)

{

        return x*2;

}

    盡管這樣的用法是正確的,但大多數(shù)C和C++的編譯器都會(huì)給出一個(gè)警告,說參數(shù)y在程序中沒有被用到。為了避免這樣的警告,C++允許聲明一個(gè)無名形參,以告訴編譯器存在該參數(shù),且調(diào)用者需要為其傳遞一個(gè)實(shí)際參數(shù),但是函數(shù)不會(huì)用到這個(gè)參數(shù)。下面給出使用了無名參數(shù)的C++函數(shù)代碼:

int fun(int x,int) //注意不同點(diǎn)

{

        return x*2;

}

2、函數(shù)的默認(rèn)參數(shù)


      C++函數(shù)的原型中可以聲明一個(gè)或多個(gè)帶有默認(rèn)值的參數(shù)。如果調(diào)用函數(shù)時(shí),省略了相應(yīng)的實(shí)際參數(shù),那么編譯器就會(huì)把默認(rèn)值作為實(shí)際參數(shù)??梢赃@樣來聲明具有默認(rèn)參數(shù)的C++函數(shù)原型:

#include iostream.h

void show(int = 1,float = 2.3,long = 6);

int main()

{

        show();

        show(2);

        show(4,5.6);

        show(8,12.34,50L);

       

        return 0;

}

void show(int first,float second,long third)

{

        cout << first =<< first

                << second =<< second

                << third =<< third << endl;

}

上面例子中,第一次調(diào)用show()函數(shù)時(shí),讓編譯器自動(dòng)提供函數(shù)原型中指定的所有默認(rèn)參數(shù),第二次調(diào)用提供了第一個(gè)參數(shù),而讓編譯器提供剩下的兩個(gè),第三次調(diào)用則提供了前面兩個(gè)參數(shù),編譯器只需提供最后一個(gè),最后一個(gè)調(diào)用則給出了所有三個(gè)參數(shù),沒有用到默認(rèn)參數(shù)。




六、函數(shù)重載


在C++中,允許有相同的函數(shù)名,不過它們的參數(shù)類型不能完全相同,這樣這些函數(shù)就可以相互區(qū)別開來。而這在C語言中是不允許的。


1、參數(shù)個(gè)數(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 << i << endl;  //輸出5

}

void a(int i,int j)

{

        cout << i << j << endl;       //輸出67

}

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 << i << j <<endl;          //輸出56

}

void a(int i,float j)

{

        cout << i << j << endl;          //輸出67.0

}



七、變量作用域      


    C++語言中,允許變量定義語句在程序中的任何地方,只要在是使用它之前就可以;而C語言中,必須要在函數(shù)開頭部分。而且C++允許重復(fù)定義變量,C語言也是做不到這一點(diǎn)的??聪旅娴某绦颍?/p>


#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<< <<a<<endl;

        }               

        return 0;

}



八、new和delete運(yùn)算符


在C++語言中,仍然支持malloc()和free()來分配和釋放內(nèi)存,同時(shí)增加了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 << I was born on

                << birthday[0] << '/' << birthday[1] << '/' << birthday[2] << endl;

        delete [] birthday;      //注意這兒

       

        return 0;

}

在刪除數(shù)組時(shí),delete運(yùn)算符后要有一對方括號(hào)。


2.為動(dòng)態(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 < size;i++)

                array = rand();

        for(i = 0;i < size;i++)

                cout << '\n' << array;

        delete [] array;

       

        return 0;

}



九、引用型變量


在C++中,引用是一個(gè)經(jīng)常使用的概念。引用型變量是其他變量的一個(gè)別名,我們可以認(rèn)為他們只是名字不相同,其他都是相同的。


1.引用是一個(gè)別名


    C++中的引用是其他變量的別名。聲明一個(gè)引用型變量,需要給他一個(gè)初始化值,在變量的生存周期內(nèi),該值不會(huì)改變。& 運(yùn)算符定義了一個(gè)引用型變量:


int a;


int& b=a;


先聲明一個(gè)名為a的變量,它還有一個(gè)別名b。我們可以認(rèn)為是一個(gè)人,有一個(gè)真名,一個(gè)外號(hào),以后不管是喊他a還是b,都是叫他這個(gè)人。同樣,作為變量,以后對這兩個(gè)標(biāo)識(shí)符操作都會(huì)產(chǎn)生相同的效果。


#include iostream.h

int main()

{

        int a = 123;

        int& b = a;

        cout << a << ','<< b << endl;       //輸出123,123

        a++;

        cout << a << ','<< b << endl;       //輸出124,124

        b++;

        cout << a<< ',' << b << endl;        //輸出125,125

        return 0;

}



2.引用的初始化

和指針不同,引用變量的值不可改變。引用作為真實(shí)對象的別名,必須進(jìn)行初始化,除非滿足下列條件之一:


(1) 引用變量被聲明為外部的,它可以在任何地方初始化


(2) 引用變量作為類的成員,在構(gòu)造函數(shù)里對它進(jìn)行初始化

(3) 引用變量作為函數(shù)聲明的形參,在函數(shù)調(diào)用時(shí),用調(diào)用者的實(shí)參來進(jìn)行初始化




3.作為函數(shù)形參的引用


引用常常被用作函數(shù)的形參。以引用代替拷貝作為形參的優(yōu)點(diǎn):


引用避免了傳遞大型數(shù)據(jù)結(jié)構(gòu)帶來的額外開銷


引用無須象指針那樣需要使用*和->等運(yùn)算符


#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 << p.n << endl;

        cout << p.text << endl;

}

void func2(s& p)

{

        cout << p.n << endl;

        cout << p.text << endl;

}

從表面上看,這兩個(gè)函數(shù)沒有明顯區(qū)別,不過他們所花的時(shí)間卻有很大差異,func2()函數(shù)所用的時(shí)間開銷會(huì)比func2()函數(shù)少很多。它們還有一個(gè)差別,如果程序遞歸func1(),隨著遞歸的深入,會(huì)因?yàn)闂5暮谋M而崩潰,但func2()沒有這樣的擔(dān)憂。



4.以引用方式調(diào)用


當(dāng)函數(shù)把引用作為參數(shù)傳遞給另一個(gè)函數(shù)時(shí),被調(diào)用函數(shù)將直接對參數(shù)在調(diào)用者中的拷貝進(jìn)行操作,而不是產(chǎn)生一個(gè)局部的拷貝(傳遞變量本身是這樣的)。這就稱為以引用方式調(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 << s;

        cout << dt.month << '/' << dt.day << '/'<< dt.year << endl;

}


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<<Enter date # (1-3,0 to quit)<<endl;

                cin>>dt;

                if(dt>0 && dt<4)

                {

                        const Date& bd = getdate(dt);

                        cout << bd.month << '/' << bd.day << '/'<< bd.year << endl;

                }

        }

        return 0;


}

   

作者:黑馬程序員C/C++培訓(xùn)學(xué)院

首發(fā): http://java.itheima.com

分享到:
在線咨詢 我要報(bào)名
和我們在線交談!