我正在设计一个输入迭代器类型,它枚举系统中所有正在运行的进程。
这类似于我设计用于枚举进程中的模块的迭代器。模块迭代器在构造函数中接受一个'process'对象,一个默认的构造迭代器被认为是一个非常结束的迭代器。
示例:
hadesmem::ModuleIterator beg(process);
hadesmem::ModuleIterator end;
assert(beg != end);
我不知道如何处理进程枚举,因为没有“状态”或信息需要给迭代器(迭代器使用Windows API在内部处理所有内容)。
示例:
// This is obviously a broken design, what is the best way to distinguish between the two?
hadesmem::ProcessIterator beg;
hadesmem::ProcessIterator end;
处理这种情况的惯用方法是什么?即,当需要向迭代器构造函数提供任何内容时,您需要区分创建“新”迭代器和非现实迭代器。
如果相关,我可以在此库中使用C ++ 11,只要它受VC11,GCC 4.7和ICC 12.1的支持。
感谢。
编辑:
为了澄清,我知道我不可能以上面发布的形式区分这两者,所以我要问的更多的是“设计”问题而不是其他任何事情...也许我是只是忽略了一些明显的事情(这不是第一次)。
答案 0 :(得分:2)
您真正想要做的是创建一种ProcessList对象,并将迭代器作为基础。我不想在每次递增迭代器时枚举所有进程或其他内容。
答案 1 :(得分:1)
如果你创建一个包含进入代表你正在迭代的快照的CreateToolhelp32Snapshot()
的参数的类,你将拥有一个自然工厂用于迭代器。这样的东西应该工作(我不在Windows上,所以没有经过测试):
class Process;
class Processes {
DWORD what, who;
public:
Processes(DWORD what, DWORD who) : what(what), who(who) {}
class const_iterator {
HANDLE snapshot;
LPPROCESSENTRY32 it;
explicit const_iterator(HANDLE snapshot, LPPROCESSENTRY32 it)
: snapshot(snapshot), it(it) {}
public:
const_iterator() : snapshot(0), it(0) {}
// the two basic functions, implement iterator requirements with these:
const_iterator &advance() {
assert(snapshot);
if ( it && !Process32Next(snapshot, &it))
it = 0;
return *this;
}
const Process dereference() const {
assert(snapshot); assert(it);
return Process(it);
}
bool equals(const const_iterator & other) const {
return handle == other.handle && it == other.it;
}
};
const_iterator begin() const {
const HANDLE snapshot = CreateToolhelp32Snapshot(what, who);
if (snapshot) {
LPPROCESSENTRY32 it;
if (Process32First(snapshot, &it))
return const_iterator(snapshot, it);
}
return end();
}
const_iterator end() const {
return const_iterator(snapshot, 0);
}
};
inline bool operator==(Processes::const_iterator lhs, Processes::const_iterator rhs) {
return lhs.equals(rhs);
}
inline bool operator!=(Processes::const_iterator lhs, Processes::const_iterator rhs) {
return !operator==(lhs, rhs);
}
用法:
int main() {
const Processes processes( TH32CS_SNAPALL, 0 );
for ( const Process & p : processes )
// ...
return 0;
}
答案 2 :(得分:1)
您可以使用named constructor idiom。
class ProcessIterator
private:
ProcessIterator(int) //begin iterator
ProcessIterator(char) //end iterator
//no default constructor, to prevent mistakes
public:
friend ProcessIterator begin() {return ProcessIterator(0);}
friend ProcessIterator end() {return ProcessIterator('\0');}
}
int main() {
for(auto it=ProcessIterator::begin(); it!=ProcessIterator::end(); ++it)
//stuff
}