首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C++ 根據函數名或行號動態選擇執行函數的實現方案

     編輯:程式設計疑難解答

需求分析

實現運行時根據用戶輸入的函數名或代碼行號,動態調用對應函數並支持循環執行。

核心方案:函數指針映射表

構建 函數名/行號 → 函數指針 的映射關係,運行時查表調用。

完整實現示例

#include <iostream>
#include <string>
#include <unordered_map>
#include <functional>
#include <vector>

// 示例業務函數
void taskA() { std::cout << "執行任務 A\n"; }
void taskB() { std::cout << "執行任務 B\n"; }
void taskC() { std::cout << "執行任務 C\n"; }

// 函數註冊表
std::unordered_map<std::string, std::function<void()>> funcMap = {
    {"taskA", taskA},
    {"taskB", taskB},
    {"taskC", taskC},
    {"1", taskA},   // 支持行號別名
    {"2", taskB},
    {"3", taskC}
};

// 也可用結構體支持更多元數據
struct FuncInfo {
    std::function<void()> func;
    std::string desc;
    int line;  // 模擬行號
};
std::unordered_map<std::string, FuncInfo> funcRegistry;

void registerFunctions() {
    funcRegistry["taskA"] = {taskA, "數據清洗", 10};
    funcRegistry["taskB"] = {taskB, "特徵提取", 25};
    funcRegistry["taskC"] = {taskC, "模型訓練", 40};
}

void executeByName(const std::string& name) {
    auto it = funcRegistry.find(name);
    if (it != funcRegistry.end()) {
        std::cout << "[" << it->second.line << "] " << it->second.desc << ": ";
        it->second.func();
    } else {
        std::cout << "未找到函數: " << name << "\n";
    }
}

void executeLoop(const std::vector<std::string>& names, int cycles) {
    for (int i = 0; i < cycles; ++i) {
        std::cout << "=== 第 " << (i+1) << " 輪 ===\n";
        for (const auto& name : names) {
            executeByName(name);
        }
    }
}

int main() {
    registerFunctions();
    
    // 單次調用
    executeByName("taskB");
    
    // 循環執行指定序列
    std::vector<std::string> pipeline = {"taskA", "taskB", "taskC"};
    executeLoop(pipeline, 2);
    
    // 交互式輸入
    std::string input;
    std::cout << "輸入函數名執行 (q 退出): ";
    while (std::cin >> input && input != "q") {
        executeByName(input);
        std::cout << "輸入函數名執行 (q 退出): ";
    }
    return 0;
}

進階擴展方案

需求實現方案關鍵技術
帶參數函數調用統一接口 void(void*) + 參數結構體類型擦除、變參模板
行號精確映射編譯期 __LINE__ 宏 + 註冊宏宏元編程、__COUNTER__
插件化動態加載動態庫 dlopen/LoadLibrary + 符號查找共享庫、C 接口導出
調試器級控制集成 libdw/DbgHelp 解析 DWARF/PDB調試信息解析、源碼映射

宏簡化註冊(推薦)

#define REGISTER_FUNC(name, desc) \
    namespace { \
        struct Register_##name { \
            Register_##name() { \
                funcRegistry[#name] = {name, desc, __LINE__}; \
            } \
        } reg_##name; \
    }

void myFunction() { ... }
REGISTER_FUNC(myFunction, "自定義業務邏輯")  // 自動註冊

注意事項

  • 生命周期管理:確保註冊的函數對象在映射表使用期間有效(靜態函數/單例/全局對象)。
  • 線程安全:多線程環境下註冊與查找需加鎖或使用無鎖容器。
  • 異常處理:被調用函數拋出異常時,調用方應捕獲並記錄,避免導致整個調度循環崩潰。
  • 性能:std::function 有微小開銷,極高頻調用可改用原始函數指針 void(*)()。

總結

通過函數指針映射表配合 std::function 實現動態分發,是 C++ 實現「按名/行號調用」的標準、高效且可擴展方案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved