试图从 Derived* 的向量中分配 Base* 的向量
Posted
技术标签:
【中文标题】试图从 Derived* 的向量中分配 Base* 的向量【英文标题】:Trying to assign vector of Base* from vector of Derived* 【发布时间】:2015-04-07 14:52:40 【问题描述】:这似乎是一个非常基本的问题,但我无法弄清楚。我有一个指向派生对象的原始指针std::vector
,我只想使用赋值运算符将它复制到另一个基指针向量。使用 VC++ 我得到错误 C2679 "binary '=': no operator found..." BTW 我不想要对象的深层副本,我只想复制指针。示例代码:
#include <vector>
using namespace std;
struct Base;
struct Derived: public Base ;
int main (int argc, char* argv[])
vector<Derived*> V1;
vector<Base*> V2;
V2 = V1; //Compiler error here
return 0;
让我感到困惑的是,我可以通过循环并使用push_back
来复制向量,如下所示:
for (Derived* p_derived : V1)
V2.push_back(p_derived);
所以我的问题是为什么分配失败,而 push_back
有效?对我来说似乎是同样的事情。
【问题讨论】:
【参考方案1】:这是因为虽然Base
和Derived
有关系,但vector<Base*>
和vector<Derived*>
之间没有关系。就类层次结构而言,它们完全不相关,因此您不能将一个分配给另一个。
您正在寻找的概念称为covariance。例如,在 Java 中,String[]
是 Object[]
的子类型。但在 C++ 中,这两种类型只是不同的类型,与String[]
和Bar
没有更多的相关性。
push_back
有效,因为该方法只需要T const&
(或T&&
),因此任何可转换为Base*
的东西都是可以接受的——Derived*
就是这样。
也就是说,vector
有一个带有一对迭代器的构造函数,在这里应该更容易使用:
vector<Base*> v2(v1.begin(), v1.end());
或者,因为它已经构建好了:
v2.assign(v1.begin(), v1.end());
【讨论】:
我想如果赋值运算符必须接受不同但相关类型的向量,它会变得过于复杂。 这也是一个(很常见的)C++ FAQ。见this。 在 C# 中,List<Base>
也与 List<Derived>
无关,但 IEnumerable<Base>
是 IEnumerable<Derived>
的子类型,因为 IEnumerable
是变体。
@usr co变体。按照常见问题解答示例,这不会违反类型安全,因为IEnumerable<T>
是只读接口,因此您不能破坏vector<Apple*>
。但是,可以想象在一个系统中,vector<T>
仍然是不变的,但存在一个 const_vector<T>
,它可能是协变的。【参考方案2】:
push_back
执行元素转换。赋值运算符只存在于相同类型的向量之间。
一个简单的解决方案是使用assign
:
v2.assign(v1.begin(), v1.end());
【讨论】:
【参考方案3】:在模板的一般情况下,如果你有一个类模板
template <typename T> struct Foo ;
Foo<Base>
不是Foo<Derived>
的基类。
因此,你不能这样做:
Foo<Derived> f1;
Foo<Base> f2 = f1;
【讨论】:
以上是关于试图从 Derived* 的向量中分配 Base* 的向量的主要内容,如果未能解决你的问题,请参考以下文章