用于对链接列表进行排序而不会出现混乱的继承

时间:2012-06-11 16:43:00

标签: c++ linked-list polymorphism

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

我正在使用链接列表,我需要对其进行两次排序:

  • 在添加列表元素时在一个参数上执行一次,
  • 经过一些处理后,在一个不同的参数上。

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

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

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

3 个答案:

答案 0 :(得分:3)

使用谓词:

std::list<Base*> myList; /* populate */

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

这假设在排序运行期间,所有元素实际上都指向Derived,它们具有成员函数foo(甚至不需要是虚拟的),它返回一个bool。

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

如果您无法确定所有元素实际上是Derived类型,那么您可以使用dynamic_cast代替,但是您必须考虑一种方法来订购所有元素无与伦比的对象。在这种情况下,最好先将范围划分为Derived和非{,1}的事物,并且只对前者进行排序。

答案 1 :(得分:1)

如果我理解正确,你就是这样的:

 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&amp;在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,以便您可以安全地检查它。

答案 2 :(得分:0)

我是否正确理解您想要对某些容器(您自己的设计)的元素进行排序,以获取如何在这些元素之间进行比较的不同版本?如果是这样,只需使用比较函数/函数提供排序算法。