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
相关产品推荐
相关产品推荐

