函數是一組一塊兒執行一個任務的語句。每一個 C++ 程序都至少有一個函數,即主函數 main() ,全部簡單的程序均可以定義其餘額外的函數。ios
你能夠把代碼劃分到不一樣的函數中。如何劃分代碼到不一樣的函數中是由你來決定的,但在邏輯上,劃分一般是根據每一個函數執行一個特定的任務來進行的。ide
函數聲明告訴編譯器函數的名稱、返回類型和參數。函數定義提供了函數的實際主體。函數
C++ 標準庫提供了大量的程序能夠調用的內置函數。例如,函數 strcat() 用來鏈接兩個字符串,函數 memcpy() 用來複制內存到另外一個位置。優化
函數還有不少叫法,好比方法、子例程或程序,等等。spa
在相同的做用域,能夠定義同名的函數,可是它們的參數要有所區分,這樣的函數構成重載關係,此外函數之間可否構成重載和返回值無關。code
小例子:遞歸
#include <iostream> using namespace std; void foo(int a) { cout << "foo(int)" << endl; } void foo(int a, int b) { cout << "foo(int, int)" << endl; } int main() { foo(1); foo(2, 3); return 0; } 返回結果: foo(int) foo(int, int)
C++編譯是經過對函數進行換名,將參數表的信息整合到新的函數名中,解決函數重載與名字衝突的矛盾。內存
經過nm查看目標文件中函數換名後的名字:ci
源文件的內容: void func(int a, int b) {} void func(int a, int b, int c) {} 生成目標文件: F:\c_projects\20181011_01>g++ -c demo3.cpp 查看目標文件信息: F:\c_projects\20181011_01>nm demo3.o 00000000 b .bss 00000000 d .data 00000000 r .eh_frame 00000000 r .rdata$zzz 00000000 t .text 00000000 T __Z4funcii // 修改後的第一個函數 00000006 T __Z4funciii // 修改後的第二個函數
當你打算讓你的C程序去調用C++的程序的時候,是沒法直接去函數的,由於C++的編譯器會將函數修更名字,固然如果直接調用C++編譯器修改後的名字也是能夠的。作用域
也能夠在函數聲明的時候加入extern "C",這樣是要求C++編譯器不對函數作換名,便於C程序去調用,可是這樣的函數沒法實現重載。
實例:
extern "C" void func(..){..} extern "C" { void func1(..){..} void func2(..){..} ... }
能夠爲函數的部分或所有形參指定缺省值,調用該函數時,若是不給實參,就取缺省值做爲相應形參的值。
例如:
#include <iostream> using namespace std; void func(int a = 1, int b = 2, int c = 3) { cout << "a = " << a << endl; cout << "b = " << b << endl; cout << "c = " << c << endl; } int main() { func(); // 當沒有給函數傳遞參數的時候,函數的參數取的是默認給的值 return 0; } 結果是: a = 1 b = 2 c = 3
缺省參數必須靠右,若是一個參數帶有缺省值,那麼右側的全部參數都必須帶有缺省值。
void func(int a = 10, int b = 20);//ok void func(int a, int b = 20);//ok void func(int a = 10, int b);//error
若是函數的定義和聲明分開,缺省參數應該寫在函數的聲明部分,而定義部分不寫。
聲明: void func(int a, int b = 100, int c = 200); 定義: void func(int a, int b, int c) {};
void func(){函數體}//函數定義
void func();//函數聲明
只有類型沒有變量名的形參稱爲啞元參數。
例如:
void func(int){};
啞元參數由於沒有變量名所以是不須要也不能被調用的。
通常在兼容舊代碼的時候會用到。
實例:
#include <iostream> using namespace std; void func(int a, int) { cout << "啞元參數" << endl; } int main() { func(10, 20); return 0; }
使用inline關鍵字修飾的函數,表示這個函數是內聯函數,編譯器將會嘗試作內聯優化,避免函數調用的開銷。
實例:
inline void func(...) {};
內聯函數僅適用於小而簡單的函數,調用次數不多或者大而複雜的函數,不適合作內聯,例如遞歸函數。
此外內聯優化知識一種建議而不是要求,可否內聯主要取決於編譯器,有些函數不加inline關鍵字也會進行內聯優化,而有些函數即使加了inline關鍵字也會被編譯器忽略。