#include <string.h>
#include <vector>
#include <algorithm>
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#include <boost/regex.hpp>
struct FileSorter{
virtual ~FileSorter(){}
virtual bool operator()(const boost::filesystem::path& p1, const boost::filesystem::path& p2) const =0;
};
struct SortByName : public FileSorter{
SortByName(bool ascending=true):ascending_order(ascending)
{
}
virtual bool operator()(const boost::filesystem::path& p1, const boost::filesystem::path& p2) const {
if(ascending_order)
return p1.stem().string() < p2.stem().string();
else
return p1.stem().string() > p2.stem().string();
}
protected:
bool ascending_order;
};
class FilesList : public std::vector<boost::filesystem::path> {
public:
FilesList(const std::string& dir, const std::string& f_regex, const FileSorter& fileSorter=SortByName()) {
boost::regex e(f_regex, boost::regex::perl);
boost::filesystem::path path(dir);
if(!boost::filesystem::is_directory(path)) {
throw std::runtime_error(path.string()+std::string(" is not a directory\n"));
}
for(boost::filesystem::directory_iterator file(path), f_end; file!= f_end; ++file){
if(boost::regex_match(file->path().filename().string(), e))
this->push_back(file->path());
}
std::sort(this->begin(), this->end(), fileSorter);
}
};
我定义了一个类FileList
,它确实执行创建符合正则表达式(f_regex
参数)的文件列表。
要对列表进行排序,可以传递SortBy***
struct(从<{1}}继承)的实例。
问题是FileSorter
函数无法使用上面的代码编译,显示以下错误消息。
/ usr / include / c ++ / 4.8 / bits / stl_algo.h:5483:5:错误:无法分配抽象类型'FileSorter'的对象
我不明白这种行为。在我的狭隘知识中,配备std::sort
的结构称为仿函数,这是将函数作为对象处理的好方法。
正如我们所知,子类的实例可以通过父类的引用来引用。
但上面的例子说的不同。
我应该更改什么才能使代码生效?
如果我对c ++有错误的概念,请不要犹豫骂我。
完整的编译错误消息在这里。
operator ()
答案 0 :(得分:4)
如果您查看签名,std::sort
会按值获取其比较对象:
template< class RandomIt, class Compare >
void sort( RandomIt first, RandomIt last, Compare comp );
所以当你写:
std::sort(this->begin(), this->end(), fileSorter);
你的对象被切片,你最终试图实例化一个按值抽取一个抽象类的函数,因此你最终得到的所有错误。
您需要做的是确保即使sort
按值进行比较,也可以通过引用传递给您。谢天谢地,有一个应用程序!只需使用std::ref
:
std::sort(this->begin(), this->end(), std::ref(fileSorter));
那就是说,真的需要一个多态比较器吗?如果您只是将不同的比较函数对象传递到FilesList
构造函数中,您应该更喜欢将其作为函数模板:
template <class Sorter>
FilesList(const std::string& dir, const std::string& f_regex, Sorter fileSorter) {
// ...
std::sort(begin(), end(), fileSorter); // now copying is fine
}
这样,您可以直接转发用户传递的内容并避免虚拟调度。
答案 1 :(得分:0)
您的FileSorter参数默认为SortByExtension对象而不是SortByName对象。由于您还没有包含SortByExtension的来源,我首先要检查SortByExtension的函数调用操作符的函数签名是
bool SortByExtension::operator()(const path&, const path&) const
如果基类和派生类函数签名之间存在任何差异,派生类函数将不会覆盖基类1,派生类将被视为抽象类。