【问题标题】:reference to a std::vector of derived class pointers as input parameter to a function引用派生类指针的 std::vector 作为函数的输入参数
【发布时间】:2010-10-13 09:36:02
【问题描述】:

首先,如果还有其他类似的问题但我没有找到,我想道歉。我一直在尝试,但由于问题非常具体,我找不到。

现在,问题来了。我有一个基类和一个派生类(比如 BNode 和 DNode ),并且我有一个 BNode* 的 std::vector。我还有一个函数,它接收对这些指针向量的引用。尝试将指向派生对象的指针的 std::vector 作为参数传递给此函数时遇到问题:

class BNode
{
};

class DNode : public BNode
{
};

class Other
{
function(std::vector<BNode*>& inputVector) { } 
}

当尝试将指针向量传递给派生类时,我从 VS 收到的错误是:

1> error C2664: 'Other::function' : cannot convert parameter 1 'std::vector<T>' to 'std::vector<T> &'
1>        with
1>        [
1>            T=DNode *
1>        ]
1>        and
1>        [
1>            T=BNode *
1>        ]

先谢谢了。

【问题讨论】:

标签: c++


【解决方案1】:

您的问题是,即使 DNode 派生自 BNodestd::vector&lt;DNode*&gt; 也不会派生自 std::vector&lt;BNode*&gt;

因此,编译器不知道如何从一种类型转换为另一种类型。

但是你可以这样做:

std::vector<BNode*> bnode_list;
std::vector<DNode*> dnode_list(bnode_list.begin(), bnode_list.end());

【讨论】:

  • 这是一个非常好的解决方案:唯一对构造函数参数也有效的建议
【解决方案2】:

这是因为vector 和vector 没有任何父子关系。它们是不同的对象。

我猜你已经创建了一个像 std::vector dnodevec; 这样的向量。 相反,您可以创建 std::vector dnodevec;作为基类指针的向量,您可以安全地在向量中插入任何 DNode 类型的指针。

【讨论】:

    【解决方案3】:

    我怀疑你可能会这样称呼Other::function

    std::vector<DNode *> v;
    // put stuff into v
    Other o;
    o.function(v);
    

    不会编译,因为 std::vector&lt;DNode *&gt;std::vector&lt;BNode *&gt; 的不同类型。

    可能适合的是:

    std::vector<BNode *> v;
    // You can put DNode * items into v
    Other o;
    o.function(v);
    

    【讨论】:

      【解决方案4】:

      不幸的是,你想要的在 C++ 中是不可能的,因为 vector&lt;BNode*&gt;vector&lt;DNode*&gt; 被认为是不相关的类型(即使 BNodeDNode 之间存在明确的关系)。

      考虑以下代码:

      class BNode
      {
      };
      
      class DNode : public BNode
      {
      };
      
      class XNode : public BNode
      {
      };
      
      void function(std::vector<BNode*>& inputVector) 
      {
        inputVector.push_back(new XNode); // This will work, as XNode derived from BNode
      } 
      
      int main()
      {
        std::vector<DNode*> vec;
      
        function(vec); // Suppose this would work
        // Then now, vec would contain a pointer to the unrelated class XNode!!
      }
      

      【讨论】:

      • 在这种情况下是正确的,如果向量是不可变的,则不适用。 C++ 在这方面有些缺陷,虽然如果目的是在每个项目上调用一些虚拟方法,则可以使用 for_each。
      【解决方案5】:

      C++ 不支持模板中的covariance。即使DNode 派生自BNode,也不能将std::vector&lt;DNode*&gt; 分配给std::vector&lt;BNode*&gt;

      为了让您的代码正常工作,您应该只声​​明指向 BNode 的指针向量,并根据需要使用指向 DNode 的指针填充它们。

      【讨论】:

        【解决方案6】:

        std::vector 不是covariant

        一般情况下,您不应将DNode * 的向量作为BNode * 的向量传递。如果function 添加或替换指向与DNode 不同的BNode 子类的指针,您将在DNode * 向量中获得非DNode 指针。

        您最好按照其他答案中的说明更改类型。

        但与其他答案所说的相反,如果function 仅读取向量,则可以传递DNode * 的向量。要标记它,请更改其签名以接受const 引用。然后你可以通过你的DNode * 向量如下:

        function(reinterpret_cast<const std::vector<BNode *> &>(vec));
        

        reinterpret_cast 通常很危险,除非您非常了解自己在做什么,否则您应该避免使用它。在这里,您绕过 C++ 类型系统将DNode * 的向量视为BNode * 的向量。原始指针是具有相同二进制表示的原始类型,与指向的类型无关。因此两种指针类型的向量都是运行时兼容的。

        【讨论】:

          猜你喜欢
          • 2016-02-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-03-20
          • 2023-03-22
          • 2016-10-03
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多