用于对链表进行排序的继承,而不会造成混乱

Inheritance for sorting a Linked List without clutter

本文关键字:混乱 继承 链表 排序 用于      更新时间:2023-10-16

我有一个看起来很简单的问题,但我找不到一个优雅的解决方案。

我正在使用一个链表,我需要对它进行两次排序:

  • 一次将一个参数添加为列表元素,并且
  • 经过一些处理后,一次在不同的参数上。

我存储在列表中的对象继承自抽象列表项基类。

问题在于重新使用第二个参数。我不想在列表项基类中为其编写纯虚拟访问器,因为我稍后在列表中存储了一些其他对象,这些对象也继承自列表项基类,但第二个访问器对它们没有意义。

我缺少一个干净的解决方案吗?

使用谓词:

std::list<Base*> myList; /* populate */
myList.sort([](Base * const p1, Base * const p2) -> bool
            { return static_cast<Derived*>(p1)->compare_with(*p2); }
           );

这假设在排序运行期间,所有元素实际上是指向Derived的指针,这些具有返回布尔值的成员函数foo(甚至不需要是虚拟的)。

当然,您可以以任何您喜欢的方式调整谓词的细节。如果您使用的是旧编译器,您还可以将 lambda 表达式替换为传统的拼写谓词类。

如果你不能确定你的所有元素实际上都是Derived类型,那么你可以用dynamic_cast来代替,但你必须想办法对所有无与伦比的对象进行排序。在这种情况下,最好先将范围划分为Derived和不,并且仅对前者进行排序。

如果我

理解正确,你有这样的东西:

 class Base {
    public:
    int getParam1() const { ... }; 
    virtual void foo() =0;  // this is an abstract class
    virtual ~Base() { ... }
 }
 class Derived : public Base {
    public:
    int getParam1() const { ... }
    int getParam2() const { ... }
 }

你在某个地方有一个std::list<Base*> myList。第一次要对列表进行排序时,执行以下操作:

sort(list.begin(),list.end(),[](const Base*v1,const Base*v2) {
    return v1->getParam1()<v2->getParam1();
});

对于第二种类型,您需要使用特定于类Derived的东西。您不想将纯虚拟访问器getParam2()添加到Base中并在Derived中实现它。但是,如果您知道您的列表包含派生对象,则可以毫无问题地使用强制转换:

sort(list.begin(),list.end(),[](const Base*b1,const Base*b2) {
    const Derived * d1 = dynamic_cast<const Derived*>(b1);
    const Derived * d2 = dynamic_cast<const Derived*>(b2);
    return d1->getParam2() < d2->getParam2();
});

请注意,如果列表中的对象不是Derived,dynamic_cast将返回nullptr以便您可以安全地检查它。

我是否正确理解您想对某个容器(您自己的设计)的元素进行排序,以便对这些元素进行比较的不同版本?如果是这样,只需为您的排序算法提供比较函子/函数。