1

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

我正在使用一个需要排序两次的链表:

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

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

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

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

4

3 回答 3

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返回布尔值的成员函数(甚至不需要是虚拟的)的指针。

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

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

于 2012-06-11T17:05:35.083 回答
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();
});

对于第二种,您需要使用特定于 class 的东西Derived。您不想将纯虚拟访问器添加getParam2()Base并在Derived. 但是,如果您知道您的列表包含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,以便您可以安全地检查它。

于 2012-06-11T17:09:21.360 回答
0

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

于 2012-06-11T17:09:00.457 回答