我有两个类,类Subclass
继承自类Superclass
:
class Superclass { /* … */ };
class Subclass : public Superclass { /* … */ };
在代码的某个地方,我还有一个向量Subclass *
。我需要使用向量,因为我想避免列表结构的另一个分配,并且向量是由其他函数返回的:
std::vector<Subclass *> &myVector = getMyVector();
我还有一个函数,我们称之为printSuperclasses
,它接受一个类型为std::vector<Superclass *> &
的参数。如何将上面显示的向量传递给函数?使用static_cast
不起作用,我希望避免使用reinterpret_cast
。
void printSuperclasses(std::vector<Superclass *> const &);
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
// or another type?
如果我理解正确,Superclass *
和Subclass *
的两个向量在内存中应该以相同的方式表示(它们是吗?(,所以我应该能够从后面的转换为第一个。有没有一种方法可以在C++中安全地?函数是否应该不将其作为向量接收,而是作为不同的东西(迭代器等(接收?
不能安全地将std::vector<Subclass *>
传递给采用std::vector<Superclass *> &
的函数。
如果它做了以下操作呢?
class Other : public Superclass {};
void takesSuperclass(std::vector<Superclass *> & vec)
{
vec.push_back(new Other);
}
现在你可能会想,但我的函数不能做到这一点。你可能是对的,但你没有告诉类型系统。
如果你想把各种各样的指针传递给takesSuperclass
,那么你可以把它做成一个模板
template<typename Supers>
auto takesSuperClass(Supers && supers)
在C++20中,您可以合理地执行这些要求
template<typename T>
using ptr_element_t = typename std::pointer_traits<T>::element_type;
template<typename Derived, typename Base>
concept derived_ptr = std::derived_from<ptr_element_t<Derived>, ptr_element_t<Base>>;
template<std::ranges::range Range>
requires derived_ptr<std::ranges::range_value_t<Range>, Super *>
auto takesSuperClass(Range supers)
如果你不想有一个模板,你也可以做一些类型擦除,例如boost::any_range
void takesSuperclass(boost::any_range<Super *, boost::forward_traversal_tag> supers)
如果您不想更改函数printSuperclasses
的签名,我建议您执行以下操作。编写一个包装函数,它将迭代器作为参数,然后在该函数中构造一个向量,稍后将传递给您提到的函数。这可以像一样完成
template<class Iter>
void printSuperclasses(Iter first, Iter last)
{
std::vector<Superclass*> superclass_vec(first, last);
printSuperclasses(superclass_vec);
}
如果Iter
是Superclass
的任何子类的指针向量的迭代器,则函数将能够转换指针。
函数的调用方式如下。
std::vector<Subclass*> subclass_vec; // not initialized, but it is not important in the case of example.
printSuperclasses(subclass_vec.begin(), subclass_vec.end());