最佳做法:将派生类的向量传递给基类向量上的方法

Best Practice: Passing a Vector of a Derived Class to a Method on a Vector of a Base Class

本文关键字:向量 基类 方法 派生 最佳      更新时间:2023-10-16

这是一个"最佳实践"问题:我可以想到几种方法,但我想知道社区认为哪一种是最好的。

我有一个方法如下:

void Foo(std::vector<BaseClass>& Objects) {...}

我现在想在Objects上调用此方法,这是一个std::vector<DerivedClass>

例如,我可以考虑使用模板,或将 Sort 转换为接受std::vector<BaseClass*>然后传递(Objects.begin(), Objects.end()).

提前谢谢。

如果你需要动态多态性,你可以考虑 std::shared_ptr、std::unique_ptr 或包含指向(内部)多态类的指针的类。换句话说,'std::vector<BaseClass*>'是丑陋的。

如果使用静态多态性(模板),则排序也将成为模板。

最佳实践是接受一对迭代器,描述Foo应该操作的元素范围,可能提供方便的函数将范围转换为迭代器:

template <typename Iter>
void Foo(Iter first, Iter last) {...}
void Foo(std::vector<BaseClass>& Objects) {
Foo(begin(Objects), end(Objects));
}
void Foo(std::vector<DerivedClass>& Objects) {
Foo(begin(Objects), end(Objects));
}
// Or even a generic range adaptor,
template <typename Range>
void Foo(Range&& r) {
using std::begin; using std::end;
Foo(begin(r), end(r));
}

你需要一个模板。

绝对没有std::vector<Base>std::vector<Derived>之间的关系,std::vector<Base*>std::vector<Derived*>之间,或任何其他包装器之间。该语言将不允许你在没有不安全的类型转换的情况下替换这些东西,这只是未定义的行为。

如果你有一个函数接受std::vector<Base%>(用任何东西替换%),那么这就是你需要传递的。唯一的方法是创建一个正确类型的新向量并填充它。

或者你使它使功能更灵活,那就是通过使其成为模板。

如果你打算对容器的元素进行操作(例如对它们进行排序),我建议你遵循人们期望的约定:即标准库中使用的模式。

template<typename RandomAccessIterator>
void foo(RandomAccessIterator start, RandomAccessIterator end) { ... }

通过这种方式,您可以轻松用于您的任一类(BaseDerived),并且查看您的代码的其他人应该能够轻松分辨出它在做什么。

如果您尝试排序,您还可以提供模板的Predicate版本,该版本允许您提供与默认值不同的排序方法(例如,如果要从大到小进行排序)。