>假设我有一个基类Base
,两个子类A
和B
,后者本身有一个子类C
。
我想通过设计强制std::vector
可以容纳任一类型的对象(包括C
等子类(,但一次只能容纳一种类型——也就是说,我有一个A
s 的向量,或者一个B
s 和C
s 的向量。
是否可以在 C++11 中拥有这个(当然,我可以在向向量添加元素时强制执行此约束,但我想知道我是否可以通过巧妙的设计来防止这种情况(?如何构建类层次结构来获得此值?
提前感谢您的帮助!
R.
boost::variant< std::vector<A>, std::vector<boost::variant<B,C>> >
描述了你的结构。
C++17 年,将boost::
替换为std::
. 两者非常相似,但不完全相同。
如果你不能使用boost
,你基本上必须编写自己的variant
。
使用有点尴尬,但您的类型限制也是如此。 在 C++14 中使用自动 lambdas(我相信这会增强变体访问者的支持(变得更加容易。
在 C++14/17 中,您可能会执行以下操作(伪代码(
template<class F, class T, class=std::enable_if_t<!is_variant<T>{}>>
decltype(auto) visit( F&& f, T&& t ) {
return std::forward<F>(f)(std::forward<T>(t));
}
my_special_vec v;
visit( [&](auto&& v){
for (auto&& e:v) {
Base* b = visit( [&](auto&& e){
e.do_operation();
return std::addressof(e);
}, decltype(e)(e));
b->do_virtual_operation();
}
}, v );
它应该在向量包含的A
、B
或C
中的任何一个上非虚拟地调用e.do_operation()
,然后在实例上调用do_virtual_operation()
作为Base
。
这是更简单的 C++14 版本。 C++11版本在函数对象和其他混乱中变得尴尬。
std::vector<T>
只能容纳一种类型的对象:T
。它永远不能保存派生对象,也不能在运行时更改类型。
通过使用间接寻址,可以单独分配对象,而是在向量中存储指向基类的指针。这允许向量指向派生对象,但不会阻止同时混合不同类型的对象。
您可以使用标记的联合实现您所描述的内容。C++11 标准库没有标记的联合类型(std::variant
将在 C++17 中引入(,因此您需要自己实现它(或者您当然可以像往常一样使用第三方实现(。标记联合允许您列出可以存储的类型,并且一次有一个类型处于活动状态。所以你可以有一个变体std::vector<A>
,std::vector<A>
和std::vector<C>
.
也就是说,您还没有描述为什么需要它,更好的设计可能是使用几个单独的向量。