如何将C++类成员方法排队运行至资源上限?求优化方案
面向对象场景下的成员函数优先级队列分批执行方案优化
问题描述
我有多个继承自父类A的子类对象,每个对象包含多个不同名称的成员函数。受资源限制无法一次性运行所有函数,希望把这些函数按优先级加入队列,分批执行。
尝试的错误实现
第一种代码因成员函数指针声明错误,触发C++编译报错:C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function,代码如下:
class A; class Token; list<Token> tokenList; class Token{ public: A* a; // 可以是A或A的子类对象 int* function; }; class A { public: A() { Token token = Token(); token.a = this; token.function = &A::hello; tokenList.push_back(token); } int hello(){ cout << "hello" << endl; return 0; } };
虚函数实现的局限
第二种通过虚函数实现的代码可运行,但不够优雅,且无法支持子类向队列传入多个不同函数,代码如下:
class A; list<A*> aList; class A { public: virtual int funct(); }; class B : public A{ public: virtual int funct(){ hello(); return 0; } int hello(){ cout << "hello" << endl; return 0; } }; int main(){ // 循环从列表中取出对象并运行函数,直到列表为空或达到最大运行函数数量 }
自行修正的方案
我自行修正的方案为:将Token类中的int* function;改为int (A::*function)();,并通过以下代码调用成员函数:
A tmp = A(); Token token = *tokenList.begin(); A *a = token.a; (a->*token.function)(); }
更优实现方式
方案1:使用std::function+std::bind封装任务
利用std::function包装任意可调用对象的特性,结合std::bind绑定成员函数和对象实例,再用std::priority_queue实现按优先级排队,是C++11后推荐的灵活方案。
#include <iostream> #include <queue> #include <functional> // 定义带优先级的任务结构体 struct Task { int priority; // 数字越大优先级越高 std::function<int()> func; // 重载比较运算符,让队列按优先级降序排列 bool operator<(const Task& other) const { return priority < other.priority; } }; std::priority_queue<Task> taskQueue; class A { public: void addTasks() { // 绑定当前对象的成员函数,按优先级加入队列 taskQueue.push({2, std::bind(&A::hello, this)}); taskQueue.push({1, std::bind(&A::world, this)}); } int hello() { std::cout << "A::hello" << std::endl; return 0; } int world() { std::cout << "A::world" << std::endl; return 0; } }; class B : public A { public: void addSubTasks() { // 子类自定义函数也可按优先级加入队列 taskQueue.push({3, std::bind(&B::foo, this)}); taskQueue.push({2, std::bind(&B::bar, this)}); } int foo() { std::cout << "B::foo" << std::endl; return 0; } int bar() { std::cout << "B::bar" << std::endl; return 0; } }; int main() { A aObj; B bObj; aObj.addTasks(); bObj.addSubTasks(); // 分批执行任务,示例每次执行2个 const int batchSize = 2; int count = 0; while (!taskQueue.empty() && count < batchSize) { Task currTask = taskQueue.top(); taskQueue.pop(); currTask.func(); count++; } // 剩余任务可在后续批次执行 return 0; }
方案2:用Lambda表达式简化绑定
如果觉得std::bind不够简洁,可直接用Lambda捕获对象指针,写法更灵活:
// A类addTasks中替换为: taskQueue.push({2, [this]() { return this->hello(); }}); taskQueue.push({1, [this]() { return this->world(); }}); // B类addSubTasks中替换为: taskQueue.push({3, [this]() { return this->foo(); }}); taskQueue.push({2, [this]() { return this->bar(); }});
方案对比
- 成员函数指针方案:语法繁琐,仅支持父类声明的成员函数,子类新增函数需类型转换,易出错
- 虚函数方案:仅能绑定固定的单个虚函数,无法支持多函数入队,扩展性差
std::function方案:灵活度高,支持任意可调用对象,代码可读性强,适配所有成员函数(父类、子类均可),还能轻松扩展任务属性
内容的提问来源于stack exchange,提问作者BankruptGreek
相关产品推荐
相关产品推荐

