C++筆記 將函式當作參數傳遞


題目

傳遞函數的位址

每個變數都有配置特定的記憶體位置,每個陣列也都有配置特定的記憶體位置,那麼函式是不是配置有記憶體位址?答案是肯定的。每個函式都有它的記憶體位置,我們可以使用函式的記憶體位置將一個函式傳入另一個函式中。但是要怎麼做?

首先,我們宣告一個函式的指標變數,用來存放函式的記憶體位址, 例如
int (*ptr)(int,int);
接著就可以把這個指標變數指向所有相同宣告原型的函式(具有兩個int資料型別的傳遞參數和int傳回型別)。

請嘗試設計一個函式其輸入為兩個指標陣列,並且函示會根據其輸入的指標函示作為依據執行,範例請看
int* mergearray(int* arr1, int* arr2, int length, int(*ptr)(int,int)){
...
}

mergearray須提供的功能有1. add、2. sub、3. mul,三樣所以各位需要再額外寫出三個函示,提供參照,範例請看

int add(int a,int b){
    ...
}
int sub(int a, int b){
    ...
}
int mul(int a,int b){
    ...
}

例一:
input自此始,但不包括此行
6
7 3 2 1 5 0
8 6 7 3 2 2
add
input至此止,但不包括此comment
output自此始,但不包括此行
15 9 9 4 7 2

完整程式碼

#include<iostream>
#include<string>
#include<vector>
using namespace std;

int add(int a,int b){
    return a+b;
}

int sub(int a, int b){
    return a-b;
}

int mul(int a,int b){
    return a*b;
}

int* mergearray(int* arr1, int* arr2, int length, int(*ptr)(int,int)){
    for(int i=0;i<length;i++){
        int num1 = *(arr1+i);
        int num2 = *(arr2+i);
        printf("%d ",ptr(num1,num2));
    }
    cout << endl ;
}

int main(){
    int inputLength;
    cin >> inputLength;

    int arr1[inputLength];
    int arr2[inputLength];
    int (*funcptr)(int,int);  // function pointer declaration 
    char sign[10];    //add/sub/mul

    for(int i=0;i<inputLength;i++){
        cin >> arr1[i];
    }

    for(int i=0;i<inputLength;i++){
        cin >> arr2[i];
    }

    //input add/sub/mul
    cin >> sign;
    string s;
    s=sign;
    if (s.compare("add") == 0) funcptr=add;
    else if (s.compare("sub") == 0) funcptr=sub;
    else if (s.compare("mul") == 0) funcptr=mul;

    //以function pointer將function當作參數傳遞
    mergearray((int*)arr1,(int*)arr2,inputLength,funcptr);
}

解題觀念&思路

reference : https://www.javatpoint.com/function-pointer-in-cpp

1.建立初始變數

int inputLength;
    cin >> inputLength;

    int arr1[inputLength];
    int arr2[inputLength];
    int (*funcptr)(int,int);  // function pointer declaration 
    char sign[10];    //add/sub/mul

    for(int i=0;i<inputLength;i++){
        cin >> arr1[i];
    }

    for(int i=0;i<inputLength;i++){
        cin >> arr2[i];
    }

array1,array2存好輸入的元素值
並定義好函數指標變數 funcptr
和輸入add/sub/mul的char[] sign

2.以''函數的指標''型態來定義變數

定義語法

[回傳值型態] (*函數名稱) (datatype arg1, datatype arg2,...);

e.g.
int (*funcptr)(int,int);
標示funcptr可以為function的變數
這個function的返回值為int , 輸入值為兩個int

所以假設

int add(int a,int b){
    return a+b;
}

int sub(int a, int b){
    return a-b;
}

int mul(int a,int b){
    return a*b;
}

int main(){
    int (*funcptr)(int,int);

    funcptr=add;
    int num = funcptr(5,5); //return 10

    funcptr=sub;
    int num = funcptr(5,5); //return 0

    funcptr=mul;
    int num = funcptr(5,5); //return 25
}

函數指數帶入參數
用跟上面宣告一樣的型態:

void func(int n1,int n2,int (*ptr)(int,int)){
    int ans = ptr(5,5); //return 10
}

int main(){
    int n1;
    int n2;
    ...
    int (*funcptr)(int,int);
    funcptr = add;
    func(n1,n2,funcptr);
}

因此我們的mergearray接到已經定義好的函數變數(add/sub/mul)
就能以ptr去使用傳進來的函數

int* mergearray(int* arr1, int* arr2, int length, int(*ptr)(int,int)){
    for(int i=0;i<length;i++){
        int num1 = *(arr1+i);
        int num2 = *(arr2+i);
        printf("%d ",ptr(num1,num2));
    }
    cout << endl ;
}







你可能感興趣的文章

CodeSandBox 載入 FontAwesome

CodeSandBox 載入 FontAwesome

不要動!把表單交出來(2) - form的enctype屬性

不要動!把表單交出來(2) - form的enctype屬性

npm ERR! enoent ENOENT: no such file or directory, open ... package.json

npm ERR! enoent ENOENT: no such file or directory, open ... package.json






留言討論