這是看第2遍,看得比較仔細,筆記如下:
函數調用在編譯期,會檢查實參與實參是否匹配。
注意,其中可能的話,會發生隱式類型轉換,編譯器只是給出警告
參數傳遞:
預設情況是按值傳遞,實參的值拷貝到參數的儲存區。函數處理的是實參的拷貝
按地址傳遞:引用和指標參數
1. 函數需要改變實參
2. 向函數傳遞大型物件時的效率考慮
3. 需要函數返回額外的結果
當需要2時,卻不希望1發生,一個解決是:將參數聲明為const參考型別
另外,如果用指標參數,需要在解引用前判斷指標是否為NULL
數組參數:
數組總是按指標傳遞
數組的長度與參數聲明無關。
一種常用的機制:
void foo(int arr[], int size);
另一種機制:聲明為數組的引用
void foo(int &arr[10]);
這樣函數會知道數組的長度,每次調用都會檢查數組實參的長度和函數定義中指定的長度是否匹配
但是,這樣缺乏靈活性
預設實參:
注意排列的順序
習慣上,預設實參在公用的標頭檔包含的函式宣告中指定,而不是在函數定義中。
如果在函數定義中指定,那麼預設實參只會用在包含函數定義的那個檔案中調用
典型情況://ff.h
int ff(int a, int b, int c = 0);
int foo(double para1, float para2 = 3.1415);
//ff.cpp
#include "ff.h"
int ff(int a, int b, int c)
{
//defination
//do something
}
int foo(double para1, float para2)
{
//also defination
//do other things
}
可以在另外一個檔案中重新聲明函數,給b和para1也提供預設參數//other .h or .cpp files
#include "ff.h"
int ff(int a, int b = 0, int c);
//錯誤寫法:
//int ff(int a, int b = 0, int c = 0);
int foo(double para1 = 1.0, float para2);
//錯誤寫法:
//int foo(double para1 = 1.0, float para2 = 3.1415);
注意理解其中錯誤寫法,也即不能給已提供預設值的參數再次指定預設值,哪怕值不變
指向函數的指標:
例如有這個函數:#include <string>
int lexicoCompare(const string &s1, const string &s2)
{
return s1.compare(s2);
}
定義:int (*pf)(const string &s1, const string &s2);
pf = lexicoCompare;
pf = &lexicoCompare;
上面2種初始化都是可以的,但是個人更傾向第2種
於是通過函數指標調用函數也有兩種用法:
pf(s1, s2);
(*pf)(s1, s2);
函數指標的數組:
int(*pf[10])(....)
函數指標可以作為函數的參數,也可以作為函數的傳回值
作為函數參數:void sort(string *, string *, int (*)(const string &, const string &));
這個複雜定義還好理解
作為函數傳回值:int (*ff(int))(int *, int);
細細拆來:整體上是聲明了一個函數ff,它有一個int類型的參數,它傳回型別為函數指標類型,為int (*)(int *, int)
哇,巨複雜,不得不贊C++的編譯器厲害。
為了更清晰的表達,最好使用typedefvoid sort(string *, string *, int (*)(const string &, const string &));
typedef int(* PF_Type)(const string &, const string &);
void sort(string *, string *, PF_Type);
int (*ff(int))(int *, int);
typedef int(* PF_Type)(int *, int);
PF_Type ff(int);
指向extern "C'函數的指標“extern "C" void (*pf)(int);
但是注意:指向C函數的指標不能用指向C++的函數的指標初始化或賦值