【摘 要】C++是在C語言的基礎上發(fā)展起來的面向過程程序設計和面向對象程序設計的一門通用語言,它不僅引入了類和對象等重要概念,而且對C語言的不足進行了改進。本文結合作者多年教學實踐,從函數、引用、I/0、內存分配等方面,對C++在非OOP方面對C的改進進行了詳細地分析和總結。
【關鍵詞】C++ OOP 引用
在面向對象的程序設計OOP(Object-Oriented Programming)方法出現以前,我們主要采用面向過程的程序設計方法,C是面向過程的程序設計語言的典型代表。早期的計算機主要用于科學計算等領域,例如計算炮彈的飛行軌跡,主要是設計出一個計算方法或解決問題的過程,所以早期的軟件開發(fā)所面臨的問題比較簡單。隨著計算機領域的擴展,計算機所處理的問題日益復雜,軟件系統(tǒng)的規(guī)模和復雜性空前擴大,以至于軟件的復雜度和其中所包含的錯誤讓程序員無法控制,所以就產生了60年代初期的軟件危機。面向對象的程序設計技術很好的解決了問題,而C++語言正是面向對象思想和技術的具體體現。C++是在C的基礎上發(fā)展起來的,不僅引入了類和對象、繼承、多態(tài)等概念,而且在非OOP方面對C也進行了改進和擴充。
一、函數方面
(一)重載/過載(overload)
C++中允許兩個或者多個不同的函數可以使用同一個函數名,即一個函數名可以對應多個函數的實現。這是C++增強的功能,C語言中是每個函數必須有唯一的名稱。例如可以在一個程序中定義兩個同名的函數int s(int x,int y){return x+y}和int s(int x,int y,int z){return x+y+z}。同一函數被多次定義或實現,編譯器會根據函數參數個數或參數類型的不同來正確的調用。在使用重載時,需要注意一下四點1.不能因為返回值類型不同而重載。例如:int max(int a,int b)和float max(int a,int b)。2.重載不是重復。例如:int max(int a,int b)和float max(int c,int d)。3.不能因為typedef而重載。如:typedef int INT; int max(int a,int b); float max(INT a,INT b),因為typedef定義的是新的類型的名字,而不是新的類型。4.防止有二義性的調用。如:int fun(int a,int b=0); int fun(int a),用fun(3)去調用。
(二)內聯函數(inline function)
因為我們在調用函數時,需要先保存現場狀態(tài)和返回地址,然后轉到子函數的代碼起始地址去執(zhí)行,子函數執(zhí)行完后,又需要取出先前保存的返回地址和現場狀態(tài),再繼續(xù)執(zhí)行,這一切都需要時間和空間方面的開銷,因此對一些功能簡單,規(guī)模較小,使用頻繁的函數,可以設計為內聯函數。聲明格式:inline 類型說明 函數名(形參表);內聯函數具有一般函數的特性,不同之處在于對函數調用的處理,它不是在函數調用時發(fā)生轉移,而是在編譯時由編譯器將函數體嵌入到每一個函數調用的語句處,這樣就節(jié)省了參數傳遞和控制轉移等開銷,從而解決了函數調用的效率問題。因為函數有跳轉和返回時,程序執(zhí)行的效率會急劇下降。他從功能上相當于C中的宏,卻沒有宏的副作用,即消除了使用宏定義#define帶來的不安全性(產生這個問題的原因是:C中宏定義#define的代碼是被直接展開的,而C++的內聯函數的代碼是被替代的)。使用時應該注意:1.內聯函數體內不能有循環(huán)語句和switch語句。2.內聯函數的定義必須出現在第一次被調用之前。3.編譯時用函數代碼替代了調用語句,增加了目標程序的代碼量,雖然不發(fā)生跳轉了,節(jié)省了時間,卻增加了空間開銷,可見,它是以空間增大的代價來換取時間的節(jié)省。
(三)函數原型(function prototype)
C語言建議我們?yōu)槊總€函數建立原型,而C++則要求必須為每個函數建立原型,說明函數的返回值類型、函數名稱、參數類型及個數。只要函數調用在自定義函數之前,程序員必須在源代碼中說明函數原型。函數原型可不包含形參變量名,只包含形參數類型名。如:int fun(int ,int);等價于int fun(int a,int b);目的是在編譯時檢查調用函數是否與預先說明的原型一致,以維護程序的正確性。函數原型格式為:返回類型 函數名(參數表);使用函數原型時應注意:1.函數原型是一條語句,必須以分號結束。2.當一個函數的定義在前而調用在后時,可以不寫它的原型,因為這時的函數定義的說明部分就起到了函數原型的作用。3.主函數不必說明原型,它被認為是一個自動說明原型的函數,且不存在被調用的問題。4.函數的原型中如果沒有寫返回類型,則C++的默認返回類型為int。5.如果沒有返回值,函數必須聲明為void,比如把main()聲明為void,則主函數中就不用寫有return 0了。
(四)缺省參數(default parameter)
C++中可以在說明函數原型或函數定義時,給一個或多個參數指定缺省值,這樣在調用該函數時,如果省略了其中的某個參數,系統(tǒng)會自動以用戶指定缺省值作為該參數的值。例如:int f(int x,int y=10);在編程時需要注意:1.當一個函數帶有多個參數時,C++沒有規(guī)定函數調用時實參的求值順序,而編譯器根據對代碼進行優(yōu)化的需要自行規(guī)定對實參的求值順序,有的編譯器規(guī)定自左向右,有的自右向左,如果實參表達式中帶有副作用的運算符(++,--等)時,可能造成二義性。例如:int add_int(int x,int y){return x+y;}void main(){int c=4,d=6;cout<< add_int(++c,c+d)< (五)形參的寫法不在支持舊式的C函數收不寫法。 intfun(int a,int b)不能寫成int a,b;int fun(x,y)。而且變量定義的位置不一定在函數的首部,可以在任意位置。C中要求所有局部變量的定義必須在執(zhí)行語句之前。 二、引用(Reference) 引用是某個變量或者對象的別名。引用的值將隨所引用的變量的值而改變。定義格式:<類型><引用名>=<初始值>;例如:int m;int n=m;n就是m的引用。需要注意的是:1.引用不占單獨的內存空間, 上面的m和n是同一變量單元。2.聲明引用時,必須對它初始化,不能聲明完成后再賦值。3.指針是通過地址間接訪問變量,引用是通過別名直接訪問變量,使用引用可以簡化程序。4.引用運算符“”僅在聲明引用時使用,其他時候“”依然表示地址操作符。引用的主要用途是可以用做函數參數和函數的返回值。 三、其他當面 (一)常量推薦用const代替define 例如:const double pi=3.1415926;const產生一個具有類型的常量。const定義一個局部變量,define范圍為整個源文件。使用const定義常量是一個標準說明語句,以分號結束。 (二)動態(tài)內存分配時使用new和delete。new和delete操作符是C++語言的一部分,無需包含頭文件 從C++的立場來看,不能使用C語言中的malloc()函數的一個原因是,它在分配空間時不能調用構造函數。類對象的建立是分配空間、構造結構以及初始化的三位一體,他們統(tǒng)一由構造函數完成。而用new創(chuàng)建對象時,會自動調用構造函數,用delete刪除對象時,也會自動調用析構函數。 (三)I/O流類控制 C語言提供的scanf()和printf()標準輸入輸出函數存在缺陷:非類型安全,不可擴充。比如C++中大量的類和對象并不是基本數據類型,C語言的輸入輸出函數根本無法識別,因此C++提供了一個I/O流庫,用cin對象來處理標準輸入,用cout來處理標準輸出。 (四)支持單行注釋// 我們可以用C語言中的/*……*/進行大范圍注釋,而用//……進行單行注釋。 四、結論 C++語言是在C語言的基礎上發(fā)展起來的,它繼承了傳統(tǒng)C語言的精華,增加了面向對象的特征,還在面向過程方面對C語言進行了許多的擴充和改進。本文從函數、引用、I/0、內存分配等方面,對這些改進進行了詳細地分析,希望對C++相關編程人員有所幫助。 參考文獻: [1]呂鳳翥.C++語言基礎教程(第二版)[M].北京:清華大學出版社,2007. [2] Bruce Eckel.C++編程思想[M],北京:機械工業(yè)出版社,2011. [3] Stanley B.Lippman.C++Primer(第四版) [M].北京:人民郵電出版社,2008. 作者簡介: 張永超(1980-),男,漢族,陜西寶雞人,吉林化工學院講師,主要從事計算機高級程序設計與數據庫等方面的研究。