如何将比较器作为函数参数传递?C++归并排序传参报错求解
解决归并排序比较器传递的C3867错误及相关问题
首先,你的代码存在几个关键问题,导致了C3867错误和潜在的逻辑错误,我来一步步帮你梳理和修正:
1. 核心错误:比较器传递方式不对
你尝试传递Point::CompareXCoordinate::operator(),这是类的非静态成员函数,这类函数必须依赖一个类的实例才能调用,直接传成员函数名的语法是错误的(C3867错误就是在提示你需要用&取地址,但即使取了地址,后续调用也需要绑定实例,非常麻烦)。
正确的做法是:直接传递CompareXCoordinate类的实例,因为它是一个仿函数类(重载了operator()),而你的mergeSort模板参数Comparator设计就是接受可调用对象(包括仿函数实例、lambda、普通函数指针等)。
2. 额外错误:索引参数传递错误
你的mergeSort函数定义中,left和right是int类型的数组索引,但你调用时传了points.begin()和points.end()(迭代器),这会导致类型不匹配,也是需要修正的点。
3. 逻辑错误:归并排序的终止条件错误
你原代码里的if (cmp(left,right))完全不对!left和right是数组索引,判断是否需要拆分递归应该用索引的大小比较(left < right),而不是用元素比较器去比较两个整数索引,这会导致排序逻辑完全混乱。
修正后的完整代码示例
第一步:修正mergeSort的模板定义和逻辑
#include <vector> // 假设Point类的定义如下(补充必要的部分) class Point { private: int x; public: int getX() const { return x; } // 你的其他Point成员... }; // 修正后的mergeSort模板 template <typename Comparable, typename Comparator> void mergeSort(vector<Comparable>& a, vector<Comparable>& tmpArray, int left, int right, Comparator cmp) { // 正确的终止条件:索引left小于right时才继续拆分 if (left < right) { int center = (left + right) / 2; mergeSort(a, tmpArray, left, center, cmp); mergeSort(a, tmpArray, center + 1, right, cmp); // 假设你的merge函数已经正确实现,会使用cmp来比较元素 merge(a, tmpArray, left, center + 1, right, cmp); } } // 你的自定义比较器类 class CompareXCoordinate { public: bool operator()(const Point& p1, const Point& p2) const { return p1.getX() < p2.getX(); } };
第二步:正确调用mergeSort
在mainDriver.cpp中:
#include <vector> // 引入Point、mergeSort、CompareXCoordinate的定义 int main() { // 初始化Point对象的vector std::vector<Point> points = {/* 你的Point实例 */}; // 临时数组需要和原数组同大小,避免merge时越界 std::vector<Point> tempArr(points.size()); // 创建比较器实例 CompareXCoordinate xCoordComparator; // 传递正确的索引(0到size-1)和比较器实例 mergeSort(points, tempArr, 0, points.size() - 1, xCoordComparator); // 或者用lambda表达式替代自定义比较器类,更简洁 // mergeSort(points, tempArr, 0, points.size() - 1, [](const Point& p1, const Point& p2) { // return p1.getX() < p2.getX(); // }); return 0; }
为什么这样能解决问题?
- 仿函数实例
xCoordComparator是一个可调用对象,直接传给mergeSort后,在merge函数中可以直接用cmp(p1, p2)的方式调用它的operator(),符合模板的设计预期。 - 传递
0和points.size()-1作为索引,匹配了mergeSort函数的参数类型要求。 - 修正后的终止条件
left < right保证了归并排序的递归拆分逻辑正确。
内容的提问来源于stack exchange,提问作者Amor Diaz
相关产品推荐
相关产品推荐

