1. 函數創建
In C++, 創建函數分爲三個步驟:
- 函數聲明 / function prototyping, function prototyping is not optional in C++. prototyping happens during compile time and is termed as "static type checking". It helps to check errors that are hard to find during run-time;
- 函數定義;
- 調用函數;
#include <iostream>
using namespace std;
//1. function prototype.
void simple();
int main() {
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
//3. call functions.
simple();
return 0;
}
/*
* 2. function definition.
*/
void simple() {
}
1. 函數聲明
爲什麼要有函數聲明呢?
- 函數聲明向編譯器描述了函數接口, 即, return type and number & type of parameters. 當一個有返回值的函數結束運算的時候,調用這個函數的函數,也許是main()需要從CPU寄存器/內存中讀取這個返回值。因爲函數聲明指定了返回值的類型,所以compilers知道how many bytes to read and how to intercept them.
- 編譯器可以確保程序員使用了正確的參數數目, 類型, 以及 return type.
函數聲明帶參數時,參數類型可以不帶參數名。
int cal(int);
int cal(int value);
如果聲明中帶參數名,函數定義時的參數名可以與聲明時的參數名不同。
Leaving the parentheses empty is the same as using the keyword "void" in the parentheses.
int cal(); == int cal(void);
2. 函數參數
int cal(double side);
1. 函數參數與數組
#include <iostream>
using namespace std;
//function prototype.
int simple(int arr[], int size);
int complex(int * arr, int size);
int main() {
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
const int size = 8;
int cookies[size] = { 1, 2, 3, 4, 5, 6, 7, 8 };
const int * px = &size;
cout<<"The size of cookies "<<sizeof(cookies)<<endl;
cout<<cookies<<" = The address of cookies"<<endl;
cout<<"The size of px "<<sizeof(px)<<endl;
//call functions.
double temp = simple(cookies, size);
cout << "total is " << temp << endl;
temp = complex(cookies, 3);
cout<<"The first 3 eaters ate ";
cout<<temp<<endl;
temp = complex(cookies + 5, 3);
cout<<"The last 3 eaters ate ";
cout<<temp<<endl;
return 0;
}
int complex(int * arr, int size) {
double total;
total = 0;
cout<<"The size of complex cookies "<<sizeof(arr)<<endl;
cout<<arr<<" = The address of complex cookies"<<endl;
for (int i = 0; i < size; i++) {
total += arr[i];
}
return total;
}
/*
* function definition.
*/
int simple(int arr[], int size) {
double total;
total = 0;
cout<<"The size of simple cookies "<<sizeof(arr)<<endl;
cout<<arr<<" = The address of simple cookies"<<endl;
for (int i = 0; i < size; i++) {
total += arr[i];
}
return total;
}
結果。
The size of cookies 32
The size of px 8
0x7fff57c72840 = The address of cookies
The size of simple cookies 8
0x7fff57c72840 = The address of simple cookies
total is 36
The size of complex cookies 8
0x7fff57c72840 = The address of complex cookies
The first 3 eaters ate 6
The size of complex cookies 8
0x7fff57c72854 = The address of complex cookies
The last 3 eaters ate 21
從結果來看,cookies是數組和指針時, 它的地址是一樣的。但是他們的sizeof()不同,sizeof(Type Array) reutrns the size of the whole array, while the sizeof(pointer-to-int) only returns the size of the pointer. 所以,在方法中我們不用sizeof()傳來的array來計算數組的size.
void show_array(const double ar[], int n);
int show_array(const double ar[],int size);
int main() {
double ar[2] = {1,2};
show_array(ar, 2);
return 0;
}
int show_array(const double ar[], int limit) {
for( int i = 0; i < limit; i++) {
cout<<ar[i] <<" ";
}
cout<<endl;
}
const double ar[] == const double *ar;
'ar' is a pointer that ponits to const double values.
2. 函數參數---數組的長度
int * pt = new int[2];
pt指向長度爲2的數組。pt指向第一個元素,pt+1指向第二個。pt+2指向數組結尾後的元素。Thus,
int * pe = pt+2;
double array_ranges(const double *begin, const double *end);
int main() {
double ar[2] = {1,2};
double temp = array_ranges(ar, ar+2);
cout<<" total is "<< temp<<endl;
return 0;
}
double array_ranges(const double *begin, const double * end) {
double total = 0;
const double * member;
for(member = begin; member!=end; member++) {
total += *member;
}
return total;
}
數組的首個元素的地址被傳遞到函數中。
3. 函數和二維數組
int data[3][4] = {{1,2,3,4}, {9,8,7,6}, {2,4,6,8}};
int total = sum(data, 3);
data is a pointer-points-to-array-of-4-int. so the appropriate way to define it is.
int total(int (*arr)[4], int size);
int sum(int arr[][4], int size);
int sum(int arr[][4], int size)
{
int total = 0;
for (int r = 0; r < size; r++)
for (int c = 0; c < 4; c++)
total += arr[r][c];
return total;
}
4. 函數與struct
void test(structX *); //prototype.
structX *m = new structX(...);
test(m);
void test(structX *);
structX m = {....};
test(&m);
函數與函數指針
- obtaining the address of a function;
- The name of a function is a pointer to that function's address in memory of the machine code.
- The pointer to a function should also acts like a pointer to the address of that function.
- Declare the pointer to a function;
- a function pointer need to specify the return value and parameter of the function.
int function1(int); //function prototype.
int (*fp)(int); //declare a function pointer.
fp = function1;
() have higher rank than *, so
*fp(int) //A function pt with parameter type int and return a pointer.
(*fp)(int) //A function pointer pt with parameter type int.
- Use Function pointers
int x = (*fp)(10);
C++ also allow
int y = fp(10);
Because of the second point in "obtaining the address of a function;"
Array of function pointers.
const double * (*f1)(const double ar[], int x);
const double * (*f2)(const double [], int);
const double* (*f3)(const double *, int);
其實擁有相同的參數列表。因爲
const double * (*pa)(const double *, int); //is a function pointer.
也可以在聲明的時候同時賦值。
const double * (*pa)(const double *, int) = f1;
OR
auto pa = f1;
Array of function pointers.
const double * (*pa[3])(const double * , int ) = {f1, f2, f3};
[] has higher rank than *, so *pa[3] is an array of three pointers. each of which is a pointer to a function that takes a const double * and int as arguments and return a const double *.
auto pb = pa;
because the name of an array is the pointer to the first element of the array. so both of pa and pb const double * px = pa[0](av, 3);
OR
cosnt double * py= (*pa[0])(av, 3);
Pointer to an array of function pointers.
*pd[3]; // array of three pointers.
(*pd)[3]; // pa is a pointer which points to array of three elements.
To combine above two togather,const double * (* /*pointer-to-*/ (*pd[3])/* array of three pointers*/)(const double *, int) = &pa;
Thus, pd points to an array, then *pd is the array of function pointers. (*pd)[i] is an array element, which is a pointer to a function.
(*pd)[i](av, 3); //function pointer
OR
*(*pd)[i](av, 3); //actual function address
注: 數組pa 和&pa也許有相同的數值,但是他們是不同的類型。
pa==&pa[0];
&pa is the address of the entire array. 例如: pa + 1指向&pa[1], &pa+1指向整個數組結尾後與數組相同大小的內存空間。
Simplify with typedef
typedef double real; //makes real as another name for double
typedef const double* (*pf)(const double *, int);
pf is now a type name.
pf p1 = f1;
p1 points to the f1() function.
pf pa[3] = {f1, f2, f3}; // pa array of 3 function pointers.
pf (*ppf)[3] = &pa; //ppf points to an array of 3 function pointers.