如何实现支持任意派生类的多态可扩展排序顺序?
这个问题我之前也碰到过,本质是要解决多态类型的可扩展排序问题,给你三个实用的方案,随便加多少派生类都能轻松搞定:
方案一:多态优先级函数(最推荐,符合开闭原则)
核心思路是给基类B加一个纯虚函数,让每个派生类自己返回对应的排序优先级。排序的时候直接调用这个虚函数比较,新增派生类只需要实现这个函数,完全不用改原来的排序逻辑。
代码示例:
#include <vector> #include <algorithm> #include <climits> class B { public: virtual ~B() = default; // 纯虚函数:返回当前类的排序优先级,值越小排越前 virtual int getSortPriority() const = 0; }; class C : public B { public: int getSortPriority() const override { return 1; // C排最前面 } }; class D : public B { public: int getSortPriority() const override { return 2; // D在C后面 } }; // 新增派生类E?太简单了,加个类实现getSortPriority就行 class E : public B { public: int getSortPriority() const override { return 3; // E在D后面 } }; // 排序用的比较函数 bool lessThan(const B* a, const B* b) { return a->getSortPriority() < b->getSortPriority(); } int main() { std::vector<B*> obj_vec; obj_vec.push_back(new D()); obj_vec.push_back(new C()); obj_vec.push_back(new E()); std::sort(obj_vec.begin(), obj_vec.end(), lessThan); // 排序后顺序:C → D → E // 记得清理内存哦 for (auto obj : obj_vec) delete obj; return 0; }
优点:完美符合开闭原则,新增类型零修改原有代码;逻辑清晰,每个类自己管理排序优先级,不容易出错。
方案二:类型注册表模式(适合基类不能修改的场景)
如果基类B是第三方库的,没法加虚函数,那可以搞个全局的类型注册表,用typeid获取对象类型,然后查注册表得到排序ID。新增派生类只需要往注册表加一行就行。
代码示例:
#include <vector> #include <algorithm> #include <typeindex> #include <unordered_map> #include <climits> class B { public: virtual ~B() = default; // 基类不能改,没虚函数 }; class C : public B {}; class D : public B {}; class E : public B {}; // 全局类型排序注册表:键是类型索引,值是排序优先级 std::unordered_map<std::type_index, int> type_sort_registry = { {std::type_index(typeid(C)), 1}, {std::type_index(typeid(D)), 2}, {std::type_index(typeid(E)), 3} }; // 新增派生类F?就加这一行: // type_sort_registry[std::type_index(typeid(F))] = 4; bool lessThan(const B* a, const B* b) { // 查找当前对象的优先级,没找到默认排最后 auto a_it = type_sort_registry.find(std::type_index(typeid(*a))); auto b_it = type_sort_registry.find(std::type_index(typeid(*b))); int a_prio = (a_it != type_sort_registry.end()) ? a_it->second : INT_MAX; int b_prio = (b_it != type_sort_registry.end()) ? b_it->second : INT_MAX; return a_prio < b_prio; } int main() { std::vector<B*> obj_vec; obj_vec.push_back(new D()); obj_vec.push_back(new C()); obj_vec.push_back(new E()); std::sort(obj_vec.begin(), obj_vec.end(), lessThan); // 顺序还是C → D → E for (auto obj : obj_vec) delete obj; return 0; }
优点:不用修改基类;注意点:依赖typeid,如果有类型擦除(比如某些多态场景)可能失效;全局注册表要注意线程安全(多线程环境下加锁)。
方案三:编译期静态优先级(追求极致性能)
如果你的场景对性能要求极高,不想有运行时的虚函数调用或哈希表查找,可以用模板元编程在编译期确定每个类的优先级。
代码示例:
#include <vector> #include <algorithm> #include <type_traits> #include <typeindex> #include <climits> class B { public: virtual ~B() = default; }; // 基模板:默认优先级最高(排最后) template<typename T> struct SortPriority { static constexpr int value = INT_MAX; }; // 给C特化优先级 template<> struct SortPriority<C> { static constexpr int value = 1; }; // 给D特化优先级 template<> struct SortPriority<D> { static constexpr int value = 2; }; class C : public B {}; class D : public B {}; class E : public B {}; // 新增E?加个特化就行: // template<> struct SortPriority<E> { static constexpr int value = 3; }; // 辅助函数:获取类型的编译期优先级 template<typename T> constexpr int getPriority() { return SortPriority<T>::value; } bool lessThan(const B* a, const B* b) { // 用typeid判断类型,然后取编译期优先级 auto a_type = std::type_index(typeid(*a)); auto b_type = std::type_index(typeid(*b)); int a_prio = INT_MAX; if (a_type == std::type_index(typeid(C))) a_prio = getPriority<C>(); else if (a_type == std::type_index(typeid(D))) a_prio = getPriority<D>(); else if (a_type == std::type_index(typeid(E))) a_prio = getPriority<E>(); int b_prio = INT_MAX; if (b_type == std::type_index(typeid(C))) b_prio = getPriority<C>(); else if (b_type == std::type_index(typeid(D))) b_prio = getPriority<D>(); else if (b_type == std::type_index(typeid(E))) b_prio = getPriority<E>(); return a_prio < b_prio; } int main() { std::vector<B*> obj_vec; obj_vec.push_back(new D()); obj_vec.push_back(new C()); obj_vec.push_back(new E()); std::sort(obj_vec.begin(), obj_vec.end(), lessThan); for (auto obj : obj_vec) delete obj; return 0; }
优点:编译期确定优先级,没有运行时开销;缺点:新增类型要写模板特化,类型多了判断逻辑会有点繁琐,适合性能敏感的场景。
内容的提问来源于stack exchange,提问作者infinitezero
相关产品推荐
相关产品推荐

