You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++命名空间环境下,如何从列表向量中调用提取的函数?

如何在仅用命名空间的库环境中调用列表向量中存储的函数指针?

我需要创建一个列表向量,每个列表用来存储函数指针的地址。现在在仅使用命名空间的库环境(不使用类)下,调用从列表中提取的函数时出现编译错误,该怎么实现这类函数的调用?

原代码

#include <list>
#include <vector>
#include <mutex>


typedef std::list<void *> funcList;

typedef struct {
  funcList* functionsList;
  char* listName;
}ListAccess_t;

namespace FuncListManager{
  //namespace {
    std::vector<funcList> funcBuffer;
    std::mutex funcMutex;
 // }

  static size_t findEmptyList() {
    for (size_t index = 0; index < funcBuffer.size(); index++) {
      if (funcBuffer[index].empty()) {
        return index;
      }
    }
    return funcBuffer.size();
  }

  size_t getAvalableListIndex() {
    std::lock_guard<std::mutex> lock(funcMutex);
    if (funcBuffer.size() != findEmptyList()) {
      return findEmptyList();
    }
    else {
      return -1;
    }
  }

  void addFunction(size_t listIndex, void* func) {
    std::lock_guard<std::mutex> lock(funcMutex);
    funcBuffer[listIndex].push_back(func);
  }

  void removeFunction(size_t listIndex, void* func) {
    std::lock_guard<std::mutex> lock(funcMutex);
    if (listIndex < funcBuffer.size()) {
      auto& myFuncList = funcBuffer[listIndex];

      auto it = std::find(myFuncList .begin(), myFuncList .end(), func);

      if (it != myFuncList .end()) {
        myFuncList .erase(it);
      }
    }
  }

  void createFunctionList(size_t capacity) {
    std::lock_guard<std::mutex> lock(funcMutex);
    funcBuffer.resize(capacity);
  }

  funcList* getFunctionListPointer(size_t listIndex) {
    std::lock_guard<std::mutex> lock(funcMutex);
    if (listIndex < funcBuffer.size()) {
      return &funcBuffer[listIndex];
    }
    return nullptr;
  }
}

void (*addNumber_t)(int a, int b);

void addnumber(int a, int b) {
  int c = a + b;
}


int main() {
  
  FuncListManager::createFunctionList(5);
  size_t index = FuncListManager::getAvalableListIndex();

  addNumber_t = &addnumber;
  FuncListManager::addObserver(index, (void*)&addnumber);
  ListAccess_t *listAccess = new ListAccess_t();

  listAccess->functionsList= FuncListManager::getObserverListPointer(index);
  listAccess->listName = "list access";

  ObserverList *list = listAccess->functionsList;

  for (auto& func: *list) {
    ((addNumber_t)func)(1,2); //how to call add function here
    int i = 0;
  }

  FuncListManager::removeFunction(index, (void*)&addnumber);

  return 0;
}

问题分析与解决

原代码的编译错误主要来自笔误和类型不安全的设计:

  • 未定义标识符:addObserver、getObserverListPointer、ObserverList都是笔误,需对应命名空间内的addFunction、getFunctionListPointer和funcList类型。
  • 类型不安全:用void*存储函数指针需要强制转换才能调用,既容易出错也不符合类型安全原则。如果所有待存储的函数签名一致,直接用对应类型的函数指针存储是最优解。

修正后的代码

#include <list>
#include <vector>
#include <mutex>
#include <algorithm> // 必须包含该头文件以使用std::find

// 直接定义匹配签名的函数指针类型,替代void*
typedef void (*AddFuncPtr)(int, int);
typedef std::list<AddFuncPtr> funcList;

typedef struct {
  funcList* functionsList;
  const char* listName; // 使用const char*避免野指针风险
} ListAccess_t;

namespace FuncListManager {
    std::vector<funcList> funcBuffer;
    std::mutex funcMutex;

    static size_t findEmptyList() {
        for (size_t index = 0; index < funcBuffer.size(); ++index) {
            if (funcBuffer[index].empty()) {
                return index;
            }
        }
        return funcBuffer.size();
    }

    // 修正拼写错误:Avalable -> Available
    size_t getAvailableListIndex() {
        std::lock_guard<std::mutex> lock(funcMutex);
        size_t emptyIdx = findEmptyList();
        // 找到空列表则返回索引,否则返回无效值(size_t为无符号类型,用(size_t)-1表示)
        return (emptyIdx < funcBuffer.size()) ? emptyIdx : (size_t)-1;
    }

    void addFunction(size_t listIndex, AddFuncPtr func) {
        std::lock_guard<std::mutex> lock(funcMutex);
        // 增加边界检查,避免越界访问
        if (listIndex < funcBuffer.size()) {
            funcBuffer[listIndex].push_back(func);
        }
    }

    void removeFunction(size_t listIndex, AddFuncPtr func) {
        std::lock_guard<std::mutex> lock(funcMutex);
        if (listIndex < funcBuffer.size()) {
            auto& myFuncList = funcBuffer[listIndex];
            auto it = std::find(myFuncList.begin(), myFuncList.end(), func);
            if (it != myFuncList.end()) {
                myFuncList.erase(it);
            }
        }
    }

    void createFunctionList(size_t capacity) {
        std::lock_guard<std::mutex> lock(funcMutex);
        funcBuffer.resize(capacity);
    }

    funcList* getFunctionListPointer(size_t listIndex) {
        std::lock_guard<std::mutex> lock(funcMutex);
        if (listIndex < funcBuffer.size()) {
            return &funcBuffer[listIndex];
        }
        return nullptr;
    }
}

void addnumber(int a, int b) {
    int c = a + b;
}

int main() {
    FuncListManager::createFunctionList(5);
    size_t index = FuncListManager::getAvailableListIndex();

    // 直接传递函数指针,无需转换为void*
    FuncListManager::addFunction(index, &addnumber);
    
    ListAccess_t* listAccess = new ListAccess_t();
    listAccess->functionsList = FuncListManager::getFunctionListPointer(index);
    listAccess->listName = "list access";

    funcList* list = listAccess->functionsList;
    // 增加空指针检查,避免非法访问
    if (list != nullptr) {
        for (auto func : *list) {
            // 直接调用函数指针,无需强制转换,类型安全
            func(1, 2);
        }
    }

    FuncListManager::removeFunction(index, &addnumber);

    delete listAccess; // 释放动态分配的内存,避免泄漏
    return 0;
}

关键改进点

  • 类型安全:用AddFuncPtr替代void*存储函数指针,消除强制转换的风险。
  • 修正笔误:修复了函数名拼写错误和未定义标识符的问题。
  • 健壮性提升:增加了越界检查、空指针检查,避免非法内存访问。
  • 内存管理:在main中释放了动态创建的listAccess,避免内存泄漏。
  • 依赖补充:添加了<algorithm>头文件,确保std::find能正常使用。

内容的提问来源于stack exchange,提问作者chandu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 07:55:57