最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語(yǔ)言仿函數(shù)(Functor)實(shí)現(xiàn)示例

 更新時(shí)間:2026年01月29日 08:50:34   作者:bkspiderx  
本文檔介紹了在C語(yǔ)言中實(shí)現(xiàn)仿函數(shù)(Functor)的方法,仿函數(shù)是一種帶狀態(tài)的可調(diào)用對(duì)象,通過結(jié)構(gòu)體和函數(shù)指針的組合模擬C++中的仿函數(shù)特性,下面就來具體介紹一下如何使用

文檔版本:V1.0
適用場(chǎng)景:C語(yǔ)言開發(fā)中需“帶狀態(tài)可調(diào)用對(duì)象”的場(chǎng)景(如自定義排序、計(jì)數(shù)器、帶配置的回調(diào)等)
前置知識(shí):C語(yǔ)言結(jié)構(gòu)體、函數(shù)指針、基本內(nèi)存操作

1. 概述

1.1 仿函數(shù)的本質(zhì)

仿函數(shù)(Functor)起源于C++,是重載operator()的類/對(duì)象,具備兩大核心特性:

  • 可調(diào)用性:像函數(shù)一樣被調(diào)用(如func());
  • 狀態(tài)持有性:可通過類的成員變量存儲(chǔ)自身狀態(tài)(如計(jì)數(shù)、配置參數(shù))。

1.2 C語(yǔ)言模擬的必要性

C語(yǔ)言沒有原生“類”和“運(yùn)算符重載”,但實(shí)際開發(fā)中常需“帶狀態(tài)的回調(diào)/函數(shù)”(如“按自定義規(guī)則排序”“帶步長(zhǎng)的計(jì)數(shù)器”)。此時(shí)需通過結(jié)構(gòu)體+函數(shù)指針模擬仿函數(shù),實(shí)現(xiàn)“可調(diào)用+持狀態(tài)”的核心能力。

1.3 C語(yǔ)言仿函數(shù)的定義

在C語(yǔ)言中,仿函數(shù)被定義為:
包含“狀態(tài)變量”和“函數(shù)指針”的結(jié)構(gòu)體——狀態(tài)變量存儲(chǔ)數(shù)據(jù),函數(shù)指針指向具體調(diào)用邏輯,調(diào)用時(shí)通過函數(shù)指針訪問狀態(tài)并執(zhí)行邏輯。

2. 核心實(shí)現(xiàn)原理

C語(yǔ)言模擬仿函數(shù)的核心是“拆分+組合”:用結(jié)構(gòu)體管理狀態(tài),用函數(shù)指針定義行為,二者結(jié)合實(shí)現(xiàn)仿函數(shù)特性。

2.1 第一步:用結(jié)構(gòu)體存儲(chǔ)“狀態(tài)”

結(jié)構(gòu)體的成員變量用于保存仿函數(shù)需要維護(hù)的數(shù)據(jù)(如計(jì)數(shù)初始值、排序方向、配置參數(shù)等),示例:

// 示例:計(jì)數(shù)器的狀態(tài)結(jié)構(gòu)體
typedef struct {
    int count;   // 狀態(tài)1:當(dāng)前計(jì)數(shù)值
    int step;    // 狀態(tài)2:計(jì)數(shù)步長(zhǎng)(可選,擴(kuò)展用)
} CounterState;

2.2 第二步:用函數(shù)指針定義“可調(diào)用邏輯”

函數(shù)指針指向具體的“調(diào)用函數(shù)”,該函數(shù)需滿足兩個(gè)要求:

  • 第一個(gè)參數(shù)必須是結(jié)構(gòu)體指針(通過指針訪問結(jié)構(gòu)體內(nèi)部狀態(tài));
  • 返回值和剩余參數(shù)根據(jù)業(yè)務(wù)場(chǎng)景定義(如計(jì)數(shù)器返回當(dāng)前值,比較器返回比較結(jié)果)。

示例函數(shù)指針定義:

// 計(jì)數(shù)器的調(diào)用函數(shù)指針:接收結(jié)構(gòu)體指針,返回當(dāng)前計(jì)數(shù)值
typedef int (*CounterCallFunc)(struct Counter* self);

2.3 第三步:組合“狀態(tài)+邏輯”為仿函數(shù)結(jié)構(gòu)體

將“狀態(tài)結(jié)構(gòu)體”與“函數(shù)指針”封裝為一個(gè)新結(jié)構(gòu)體,形成完整的仿函數(shù)類型:

// 完整的計(jì)數(shù)器仿函數(shù)結(jié)構(gòu)體
typedef struct Counter {
    // 狀態(tài)部分:復(fù)用上面的狀態(tài)結(jié)構(gòu)體(或直接定義成員)
    int count;
    int step;
    // 邏輯部分:函數(shù)指針(指向具體調(diào)用邏輯)
    CounterCallFunc call;
} Counter;

2.4 第四步:初始化仿函數(shù)

提供初始化函數(shù),完成“狀態(tài)賦值”和“函數(shù)指針綁定”,確保仿函數(shù)創(chuàng)建后可直接使用:

// 初始化計(jì)數(shù)器仿函數(shù):參數(shù)為初始值和步長(zhǎng)
Counter Counter_Create(int initial, int step) {
    Counter cnt;
    // 初始化狀態(tài)
    cnt.count = initial;
    cnt.step = step;
    // 綁定調(diào)用邏輯(關(guān)聯(lián)具體的函數(shù))
    cnt.call = Counter_Increment;
    return cnt;
}

3. 實(shí)戰(zhàn)示例

以下兩個(gè)示例覆蓋“基礎(chǔ)狀態(tài)計(jì)數(shù)”和“帶狀態(tài)回調(diào)”兩大核心場(chǎng)景,代碼可直接編譯運(yùn)行。

3.1 示例1:帶步長(zhǎng)的計(jì)數(shù)器仿函數(shù)

功能需求

  • 初始化時(shí)設(shè)置“初始值”和“步長(zhǎng)”;
  • 每次調(diào)用仿函數(shù),按步長(zhǎng)自增并返回當(dāng)前值;
  • 支持動(dòng)態(tài)修改步長(zhǎng)(修改狀態(tài))。

完整代碼

#include <stdio.h>

// 1. 定義計(jì)數(shù)器仿函數(shù)結(jié)構(gòu)體(狀態(tài)+邏輯)
typedef struct Counter {
    // 狀態(tài):計(jì)數(shù)值、步長(zhǎng)
    int count;
    int step;
    // 邏輯:調(diào)用函數(shù)指針(接收自身指針,返回當(dāng)前值)
    int (*call)(struct Counter* self);
} Counter;

// 2. 實(shí)現(xiàn)調(diào)用邏輯:按步長(zhǎng)自增并返回當(dāng)前值
int Counter_Increment(Counter* self) {
    // 通過結(jié)構(gòu)體指針訪問內(nèi)部狀態(tài)
    self->count += self->step;
    return self->count;
}

// 3. 初始化函數(shù):創(chuàng)建仿函數(shù)實(shí)例
Counter Counter_Create(int initial, int step) {
    Counter cnt;
    cnt.count = initial;
    cnt.step = step;
    cnt.call = Counter_Increment; // 綁定邏輯
    return cnt;
}

// 4. 輔助函數(shù):動(dòng)態(tài)修改步長(zhǎng)(修改狀態(tài))
void Counter_SetStep(Counter* self, int new_step) {
    self->step = new_step;
}

// 主函數(shù)測(cè)試
int main() {
    // 創(chuàng)建仿函數(shù)實(shí)例:初始值0,步長(zhǎng)1
    Counter cnt = Counter_Create(0, 1);
    
    // 調(diào)用仿函數(shù)(像函數(shù)一樣使用)
    printf("第1次調(diào)用:%d\n", cnt.call(&cnt)); // 輸出:1
    printf("第2次調(diào)用:%d\n", cnt.call(&cnt)); // 輸出:2
    
    // 修改狀態(tài)(步長(zhǎng)改為3)
    Counter_SetStep(&cnt, 3);
    printf("修改步長(zhǎng)為3后,第3次調(diào)用:%d\n", cnt.call(&cnt)); // 輸出:5
    printf("第4次調(diào)用:%d\n", cnt.call(&cnt)); // 輸出:8
    
    return 0;
}

編譯與運(yùn)行

  • 編譯命令:gcc counter_functor.c -o counter_functor
  • 運(yùn)行結(jié)果:
    第1次調(diào)用:1
    第2次調(diào)用:2
    修改步長(zhǎng)為3后,第3次調(diào)用:5
    第4次調(diào)用:8
    

3.2 示例2:帶排序方向的比較器仿函數(shù)

功能需求

  • 實(shí)現(xiàn)自定義排序:支持“升序”和“降序”切換;
  • 排序邏輯通過仿函數(shù)封裝(狀態(tài):排序方向;邏輯:比較規(guī)則);
  • 復(fù)用排序函數(shù),僅需修改仿函數(shù)狀態(tài)即可切換排序方向。

完整代碼

#include <stdio.h>
#include <stdlib.h>

// 1. 定義比較器仿函數(shù)結(jié)構(gòu)體(狀態(tài)+邏輯)
typedef struct Comparator {
    // 狀態(tài):排序方向(1=升序,0=降序)
    int is_ascending;
    // 邏輯:比較函數(shù)指針(接收自身、兩個(gè)待比較值,返回比較結(jié)果)
    int (*compare)(struct Comparator* self, int a, int b);
} Comparator;

// 2. 實(shí)現(xiàn)比較邏輯:根據(jù)狀態(tài)返回比較結(jié)果
int Int_Compare(Comparator* self, int a, int b) {
    if (self->is_ascending) {
        return a - b; // 升序:a>b返回正數(shù),觸發(fā)交換
    } else {
        return b - a; // 降序:b>a返回正數(shù),觸發(fā)交換
    }
}

// 3. 初始化比較器仿函數(shù)
Comparator Comparator_Create(int is_ascending) {
    Comparator cmp;
    cmp.is_ascending = is_ascending;
    cmp.compare = Int_Compare;
    return cmp;
}

// 4. 通用排序函數(shù)(接收仿函數(shù)作為參數(shù),復(fù)用邏輯)
void Sort_With_Functor(int* arr, int len, Comparator* cmp) {
    for (int i = 0; i < len - 1; i++) {
        for (int j = 0; j < len - i - 1; j++) {
            // 調(diào)用仿函數(shù)的比較邏輯
            if (cmp->compare(cmp, arr[j], arr[j+1]) > 0) {
                // 交換元素
                int temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }
}

// 輔助函數(shù):打印數(shù)組
void Print_Array(int* arr, int len) {
    for (int i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

// 主函數(shù)測(cè)試
int main() {
    int arr[] = {5, 2, 9, 1, 5, 6};
    int len = sizeof(arr) / sizeof(arr[0]);
    
    printf("原始數(shù)組:");
    Print_Array(arr, len); // 輸出:5 2 9 1 5 6
    
    // 1. 升序排序(使用升序比較器)
    Comparator asc_cmp = Comparator_Create(1);
    Sort_With_Functor(arr, len, &asc_cmp);
    printf("升序排序后:");
    Print_Array(arr, len); // 輸出:1 2 5 5 6 9
    
    // 2. 降序排序(復(fù)用排序函數(shù),僅修改比較器狀態(tài))
    Comparator desc_cmp = Comparator_Create(0);
    Sort_With_Functor(arr, len, &desc_cmp);
    printf("降序排序后:");
    Print_Array(arr, len); // 輸出:9 6 5 5 2 1
    
    return 0;
}
編譯與運(yùn)行
  • 編譯命令:gcc comparator_functor.c -o comparator_functor
  • 運(yùn)行結(jié)果:
    原始數(shù)組:5 2 9 1 5 6 
    升序排序后:1 2 5 5 6 9 
    降序排序后:9 6 5 5 2 1 
    

4. 特點(diǎn)與局限

4.1 優(yōu)點(diǎn)

  1. 靈活性高:相比單純的函數(shù)指針,可攜帶狀態(tài),支持動(dòng)態(tài)調(diào)整邏輯(如示例2切換排序方向);
  2. 復(fù)用性強(qiáng):核心邏輯(如排序函數(shù))可復(fù)用,僅需替換仿函數(shù)實(shí)例即可改變行為;
  3. 貼近C語(yǔ)言特性:基于結(jié)構(gòu)體和函數(shù)指針實(shí)現(xiàn),無額外依賴,兼容性好。

4.2 局限

  1. 無類型安全:需手動(dòng)保證“函數(shù)指針參數(shù)”與“結(jié)構(gòu)體類型”匹配,編譯器不報(bào)錯(cuò)(如將Counter*傳給Comparator*會(huì)導(dǎo)致運(yùn)行時(shí)錯(cuò)誤);
  2. 語(yǔ)法繁瑣:調(diào)用時(shí)需顯式傳入結(jié)構(gòu)體指針(如cnt.call(&cnt)),不如C++仿函數(shù)簡(jiǎn)潔;
  3. 泛化能力弱:不支持C++模板的泛型,需為不同類型(如int/float)單獨(dú)定義仿函數(shù)結(jié)構(gòu)體(如IntComparator/FloatComparator)。

5. 常見問題(FAQ)

Q1:為什么調(diào)用仿函數(shù)時(shí)必須傳結(jié)構(gòu)體指針(如cnt.call(&cnt))?

A:因?yàn)楹瘮?shù)指針需要通過指針訪問結(jié)構(gòu)體內(nèi)部的狀態(tài)變量(如count/is_ascending)。若傳值(cnt.call(cnt)),會(huì)創(chuàng)建結(jié)構(gòu)體副本,修改的是副本狀態(tài),原實(shí)例狀態(tài)不變。

Q2:能否將仿函數(shù)結(jié)構(gòu)體定義為指針類型(如Counter*)?

A:可以。若需動(dòng)態(tài)分配內(nèi)存(如在堆上創(chuàng)建仿函數(shù)),可將初始化函數(shù)改為返回指針:

// 動(dòng)態(tài)創(chuàng)建計(jì)數(shù)器仿函數(shù)(堆內(nèi)存)
Counter* Counter_Create_Dynamic(int initial, int step) {
    Counter* cnt = (Counter*)malloc(sizeof(Counter));
    if (cnt != NULL) {
        cnt->count = initial;
        cnt->step = step;
        cnt->call = Counter_Increment;
    }
    return cnt;
}

注意:動(dòng)態(tài)創(chuàng)建后需手動(dòng)調(diào)用free(cnt)釋放內(nèi)存,避免內(nèi)存泄漏。

Q3:函數(shù)指針的語(yǔ)法太復(fù)雜,有沒有簡(jiǎn)化方式?

A:可通過typedef為函數(shù)指針定義別名,簡(jiǎn)化代碼。如示例2中:

// 簡(jiǎn)化前:直接在結(jié)構(gòu)體中定義函數(shù)指針
typedef struct Comparator {
    int is_ascending;
    int (*compare)(struct Comparator* self, int a, int b);
} Comparator;

// 簡(jiǎn)化后:先typedef函數(shù)指針,再在結(jié)構(gòu)體中使用別名
typedef int (*CompareFunc)(struct Comparator* self, int a, int b);
typedef struct Comparator {
    int is_ascending;
    CompareFunc compare; // 更簡(jiǎn)潔
} Comparator;

6. 擴(kuò)展場(chǎng)景

6.1 帶多狀態(tài)的仿函數(shù)

示例:實(shí)現(xiàn)“帶范圍限制的計(jì)數(shù)器”,狀態(tài)包括count(當(dāng)前值)、min(最小值)、max(最大值),調(diào)用時(shí)若超出范圍則觸發(fā)邊界處理:

typedef struct RangeCounter {
    int count;
    int min;
    int max;
    int (*call)(struct RangeCounter* self); // 調(diào)用時(shí)自增,超出范圍返回-1
} RangeCounter;

int RangeCounter_Increment(RangeCounter* self) {
    if (self->count >= self->max) {
        printf("已達(dá)最大值!\n");
        return -1;
    }
    self->count++;
    return self->count;
}

// 初始化:初始值0,范圍[0,5]
RangeCounter RangeCounter_Create(int min, int max) {
    RangeCounter cnt;
    cnt.count = min;
    cnt.min = min;
    cnt.max = max;
    cnt.call = RangeCounter_Increment;
    return cnt;
}

6.2 仿函數(shù)數(shù)組

可將多個(gè)仿函數(shù)實(shí)例存入數(shù)組,實(shí)現(xiàn)“批量調(diào)用”。如多個(gè)不同步長(zhǎng)的計(jì)數(shù)器:

int main() {
    // 創(chuàng)建3個(gè)不同步長(zhǎng)的計(jì)數(shù)器
    Counter counters[3] = {
        Counter_Create(0, 1),
        Counter_Create(0, 2),
        Counter_Create(0, 3)
    };
    
    // 批量調(diào)用仿函數(shù)
    for (int i = 0; i < 3; i++) {
        printf("計(jì)數(shù)器%d第1次調(diào)用:%d\n", i+1, counters[i].call(&counters[i]));
    }
    // 輸出:
    // 計(jì)數(shù)器1第1次調(diào)用:1
    // 計(jì)數(shù)器2第1次調(diào)用:2
    // 計(jì)數(shù)器3第1次調(diào)用:3
    return 0;
}

到此這篇關(guān)于C語(yǔ)言仿函數(shù)(Functor)實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)C語(yǔ)言仿函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++關(guān)于構(gòu)造函數(shù)可向父類或者本類傳參的講解

    C++關(guān)于構(gòu)造函數(shù)可向父類或者本類傳參的講解

    今天小編就為大家分享一篇關(guān)于C++關(guān)于構(gòu)造函數(shù)可向父類或者本類傳參的講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • C++17文件系統(tǒng)庫(kù)之std::filesystem 示例詳解

    C++17文件系統(tǒng)庫(kù)之std::filesystem 示例詳解

    std::filesystem是C++17引入的一個(gè)強(qiáng)大且易用的文件系統(tǒng)操作庫(kù),它提供了跨平臺(tái)的文件系統(tǒng)操作接口,簡(jiǎn)化了文件和目錄操作的代碼實(shí)現(xiàn),本文給大家介紹C++17文件系統(tǒng)庫(kù)之std::filesystem 示例詳解,感興趣的朋友一起看看吧
    2025-03-03
  • C語(yǔ)言中的盜賊(小偷)問題詳解

    C語(yǔ)言中的盜賊(小偷)問題詳解

    大家好,本篇文章主要講的是C語(yǔ)言中的盜賊(小偷)問題詳解,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-01-01
  • C++超集C++/CLI模塊的基本語(yǔ)法

    C++超集C++/CLI模塊的基本語(yǔ)法

    這篇文章介紹了C++超集C++/CLI模塊的基本語(yǔ)法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07
  • 基于QT5實(shí)現(xiàn)一個(gè)時(shí)鐘桌面

    基于QT5實(shí)現(xiàn)一個(gè)時(shí)鐘桌面

    這篇文章主要介紹了利用QT5實(shí)現(xiàn)的一個(gè)時(shí)鐘桌面,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定的幫助,感興趣的小伙伴可以了解一下
    2022-01-01
  • C語(yǔ)言指針變量作為函數(shù)參數(shù)的實(shí)現(xiàn)步驟詳解

    C語(yǔ)言指針變量作為函數(shù)參數(shù)的實(shí)現(xiàn)步驟詳解

    這篇文章主要介紹了C語(yǔ)言指針變量作為函數(shù)參數(shù)的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2023-02-02
  • 解決scanf_s輸入%d%c%d格式錯(cuò)誤的問題

    解決scanf_s輸入%d%c%d格式錯(cuò)誤的問題

    這篇文章主要介紹了解決scanf_s輸入%d%c%d格式錯(cuò)誤的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • C/C++詳解實(shí)現(xiàn)二層轉(zhuǎn)發(fā)

    C/C++詳解實(shí)現(xiàn)二層轉(zhuǎn)發(fā)

    數(shù)據(jù)鏈路層是開放系統(tǒng)互連 (OSI) 模型中的第二層,該層用于通過 LAN 等單一網(wǎng)絡(luò)進(jìn)行通信的節(jié)點(diǎn),第二層數(shù)據(jù)包不能從一個(gè)網(wǎng)絡(luò)傳輸?shù)搅硪粋€(gè)網(wǎng)絡(luò)。而二層轉(zhuǎn)發(fā)是根據(jù)報(bào)文的目的MAC直接進(jìn)行轉(zhuǎn)發(fā),轉(zhuǎn)發(fā)過程中不用對(duì)報(bào)文的頭部做任何的修改
    2022-05-05
  • C++細(xì)講深淺拷貝與初始化列表如何操作

    C++細(xì)講深淺拷貝與初始化列表如何操作

    C++對(duì)象特性里的拷貝構(gòu)造函數(shù)有更深入的含義,而且面試曾經(jīng)問過關(guān)于拷貝的析構(gòu)問題,那么今天就好好解析一下深淺拷貝的問題;還有初始化列表的形式,這個(gè)在給對(duì)象屬性初始化的時(shí)候非常方便,建議大家熟練掌握,話不多說,開始正文
    2022-05-05
  • C語(yǔ)言利用面試真題理解指針的使用

    C語(yǔ)言利用面試真題理解指針的使用

    C語(yǔ)言這門課程在計(jì)算機(jī)的基礎(chǔ)教學(xué)中一直占有比較重要的地位,然而要想突破C語(yǔ)言的學(xué)習(xí),對(duì)指針的掌握是非常重要的,本文將具體針對(duì)指針的基礎(chǔ)做詳盡的介紹
    2022-08-08

最新評(píng)論

昭通市| 彩票| 剑河县| 读书| 尼玛县| 吉木萨尔县| 图木舒克市| 蒲江县| 宣威市| 翁源县| 新平| 西丰县| 大同市| 噶尔县| 和顺县| 玉屏| 抚顺县| 应用必备| 桐城市| 扎兰屯市| 泾阳县| 江山市| 屏东市| 乌拉特前旗| 错那县| 翁牛特旗| 申扎县| 庆云县| 阿拉善左旗| 屏东市| 晋州市| 普格县| 赣榆县| 华亭县| 土默特右旗| 红原县| 富民县| 彭阳县| 环江| 大丰市| 马山县|