我有一个看起来很简单的问题,但我找不到一个优雅的解决方案。
我正在使用一个需要排序两次的链表:
- 在添加列表元素时一次性添加一个参数,并且
- 经过一些处理后,在不同的参数上一次。
我存储在列表中的对象继承自抽象列表项基类。
问题在于诉诸第二个参数。我不想在列表项基类中为它编写一个纯虚拟访问器,因为我后来在列表中存储了一些其他对象,这些对象也继承自列表项基类,但是第二个访问器对他们。
我缺少一个干净的解决方案吗?
我有一个看起来很简单的问题,但我找不到一个优雅的解决方案。
我正在使用一个需要排序两次的链表:
我存储在列表中的对象继承自抽象列表项基类。
问题在于诉诸第二个参数。我不想在列表项基类中为它编写一个纯虚拟访问器,因为我后来在列表中存储了一些其他对象,这些对象也继承自列表项基类,但是第二个访问器对他们。
我缺少一个干净的解决方案吗?
使用谓词:
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
和不存在的东西,并且只对前者进行排序。
如果我理解正确,你有类似的东西:
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
,以便您可以安全地检查它。
我是否正确理解您想要对某些容器(您自己设计的)的元素进行排序,以便在这些元素之间进行比较的不同版本?如果是这样,只需为您的排序算法提供比较函子/函数。