【问题标题】:Trying to assign vector of Base* from vector of Derived*试图从 Derived* 的向量中分配 Base* 的向量
【发布时间】: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 有效?对我来说似乎是同样的事情。

【问题讨论】:

    标签: c++ pointers inheritance vector


    【解决方案1】:

    这是因为虽然BaseDerived 有关系,但vector&lt;Base*&gt;vector&lt;Derived*&gt; 之间没有关系。就类层次结构而言,它们完全不相关,因此您不能将一个分配给另一个。

    您正在寻找的概念称为covariance。例如,在 Java 中,String[]Object[] 的子类型。但在 C++ 中,这两种类型只是不同的类型,与String[]Bar 没有更多的相关性。

    push_back 有效,因为该方法只需要T const&amp;(或T&amp;&amp;),因此任何可转换为Base* 的东西都是可以接受的——Derived* 就是这样。

    也就是说,vector 有一个带有一对迭代器的构造函数,在这里应该更容易使用:

    vector<Base*> v2(v1.begin(), v1.end());
    

    或者,因为它已经构建好了:

    v2.assign(v1.begin(), v1.end());
    

    【讨论】:

    • 我想如果赋值运算符必须接受不同但相关类型的向量,它会变得过于复杂。
    • 这也是一个(很常见的)C++ FAQ。见this
    • 在 C# 中,List&lt;Base&gt; 也与 List&lt;Derived&gt; 无关,但 IEnumerable&lt;Base&gt;IEnumerable&lt;Derived&gt; 的子类型,因为 IEnumerable 是变体。
    • @usr co变体。按照常见问题解答示例,这不会违反类型安全,因为IEnumerable&lt;T&gt; 是只读接口,因此您不能破坏vector&lt;Apple*&gt;。但是,可以想象在一个系统中,vector&lt;T&gt; 仍然是不变的,但存在一个 const_vector&lt;T&gt;,它可能是协变的。
    【解决方案2】:

    push_back 执行元素转换。赋值运算符只存在于相同类型的向量之间。

    一个简单的解决方案是使用assign

    v2.assign(v1.begin(), v1.end());
    

    【讨论】:

      【解决方案3】:

      在模板的一般情况下,如果你有一个类模板

      template <typename T> struct Foo {};
      

      Foo&lt;Base&gt; 不是Foo&lt;Derived&gt; 的基类。

      因此,你不能这样做:

      Foo<Derived> f1;
      Foo<Base> f2 = f1;
      

      【讨论】:

        猜你喜欢
        • 2014-07-21
        • 2021-06-21
        • 1970-01-01
        • 1970-01-01
        • 2023-02-07
        • 1970-01-01
        • 1970-01-01
        • 2011-01-03
        • 1970-01-01
        相关资源
        最近更新 更多