如何在C++中为两个类复用堆代码,避免重复实现
问题根源
你的vector<Job> heap直接存储抽象类Job的对象,而抽象类无法被实例化;同时即使Job不是抽象类,直接存储对象会触发对象切片,丢失子类的多态特性,导致无法调用子类的getValue和setValue实现。
解决方案一:用智能指针存储多态对象
将HeapStruct中的容器改为存储智能指针(推荐unique_ptr),既能保留多态特性,又能避免内存泄漏:
修改HeapStruct核心代码:
#include <memory> // 引入智能指针头文件 class HeapStruct{ private: vector<unique_ptr<Job>> heap; // 替换为智能指针容器 long long size; long long maxSize; // ...其他私有成员 public: HeapStruct(long long maxSize) : maxSize(maxSize), size(0) { heap.reserve(maxSize); // 预分配空间 } long long getValueAt(long long i) { return heap.at(i)->getValue(); // 通过指针调用虚函数 } // 插入节点:接收子类的智能指针 void insertNode(unique_ptr<Job> job) { if (size >= maxSize) return; heap.push_back(move(job)); siftUp(size); size++; } // 获取最小值:返回智能指针 unique_ptr<Job> getMin() { if (size == 0) return nullptr; return move(heap[0]); } // 堆上浮逻辑适配指针调用 void siftUp(long long i) { while (i > 0) { long long parent = (i - 1) / 2; if (heap[i]->getValue() >= heap[parent]->getValue()) break; swap(heap[i], heap[parent]); i = parent; } } // siftDown/removeNode等操作同理,均改为通过指针调用虚函数 };
使用示例:
// 创建AvailableJob堆 HeapStruct availableHeap(100); availableHeap.insertNode(make_unique<AvailableJob>(10, 20)); // 创建UsedJob堆 HeapStruct usedHeap(100); usedHeap.insertNode(make_unique<UsedJob>(10, 20));
更优方案:用自定义比较器替代继承
无需修改原Job类结构,也不需要子类,直接给HeapStruct传入"取值逻辑",实现基于不同字段的排序,灵活性更高:
修改HeapStruct为带自定义逻辑的版本:
#include <functional> // 引入function头文件 class HeapStruct{ private: vector<Job> heap; long long size; long long maxSize; function<long long(const Job&)> getTargetValue; // 存储获取排序字段的函数 public: // 构造函数传入取值逻辑 HeapStruct(long long maxSize, function<long long(const Job&)> func) : maxSize(maxSize), size(0), getTargetValue(func) { heap.reserve(maxSize); } long long getValueAt(long long i) { return getTargetValue(heap.at(i)); } void insertNode(const Job& job) { if (size >= maxSize) return; heap.push_back(job); siftUp(size); size++; } // 堆上浮逻辑基于自定义取值函数 void siftUp(long long i) { while (i > 0) { long long parent = (i - 1) / 2; if (getTargetValue(heap[i]) >= getTargetValue(heap[parent])) break; swap(heap[i], heap[parent]); i = parent; } } Job getMin() { if (size == 0) throw runtime_error("Heap is empty"); return heap[0]; } // ...其他堆操作 };
使用示例:
// 基于value1的最小堆 HeapStruct heapByValue1(100, [](const Job& job) { return job.value1; }); heapByValue1.insertNode(Job(5, 10)); // 基于value2的最小堆 HeapStruct heapByValue2(100, [](const Job& job) { return job.value2; }); heapByValue2.insertNode(Job(5, 10));
这种方案避免了继承带来的耦合,同时支持快速扩展更多排序字段。
内容的提问来源于stack exchange,提问作者ad_valle
相关产品推荐
相关产品推荐

