我认为在 C++11 中,您所描述的方式已经非常接近,但我可能错了。 C++17大大扩展了algorithms library,所以你可以使用std::for_each。
为了演示这一点,让我们给类一些功能并创建一个实例向量(或列表):
class A {
public:
virtual std::string name() const = 0;
};
class B : public A {
public:
virtual std::string name() const override {
return "Class B";
}
};
class C : public A {
public:
virtual std::string name() const override {
return "Class C";
}
};
int main()
{
std::vector<A*> vec { new B(), new B(), new C(), new C(), new B() };
}
现在使用for_each,您可以重新编写循环:
std::for_each(std::begin(vec), std::end(vec), [](const A* val) {
auto B* b = dynamic_cast<B*>(val);
if (b)
std::cout << b->name() << std::endl;
});
不幸的是,任何算法都没有内置过滤器。但是,您可以实现类似for_each_if:
template<typename Iterator, typename Predicate, typename Operation> void
for_each_if(Iterator begin, Iterator end, Predicate pred, Operation op) {
std::for_each(begin, end, [&](const auto p) {
if (pred(p))
op(p);
});
}
并像这样使用它:
for_each_if(std::begin(vec), std::end(vec),
[](A* val) { return dynamic_cast<B*>(val) != nullptr; },
[](const A* val) {
std::cout << val->name() << std::endl;
}
);
或者对于您的具体情况,您可以更加专门化实现:
template<typename T, typename Iterator, typename Operation> void
dynamic_for_each(Iterator begin, Iterator end, Operation op) {
std::for_each(begin, end, [&](auto p) {
auto tp = dynamic_cast<T>(p);
if (tp)
op(tp);
});
}
并像这样使用它:
dynamic_for_each<B*>(std::begin(vec), std::end(vec), [](const B* val) {
std::cout << val->name() << std::endl;
});
所有三个实现都打印相同的输出:
B类
B类
B类