【问题标题】:Conversion between C++ vector of base and derived classes基类和派生类的 C++ 向量之间的转换
【发布时间】:2021-04-22 16:55:02
【问题描述】:

请看下面的代码,你可以将它编译为一个单独的 .cpp 文件,但你应该把基础库代码想象成一个单独的包:

#include <iostream>
#include <memory>
#include <vector>

// Start of classes defined in a base library shared by many projects

class BaseObject
{
    public:

        BaseObject() : value(0) {}

        BaseObject(int val) : value(val) {}

    protected:

        int value;
};

class BaseObjectHandler
{
    public:

        void setVector(std::unique_ptr<std::vector<BaseObject>>&& v)
        {
            vec = std::move(v);
        }

    protected:

        std::unique_ptr<std::vector<BaseObject>> vec;
};

// End of classes defined in a base library shared by many projects

// Start of specific implementation for project A

class SpecificObject : public BaseObject
{
    public:

        SpecificObject() : BaseObject(0) {}
};

class SpecificObjectHandler : public BaseObjectHandler
{
    public:

        void doSomethingOnVector()
        {
            // Do something on vector
        }
};

int main()
{
    SpecificObjectHandler handler;

    handler.setVector(std::make_unique<std::vector<SpecificObject>>());

    handler.doSomethingOnVector();

    exit(0);
}

// End of specific implementation for project A

BaseObjectHandler 可以与其派生处理程序共享一些常用操作,但对 SpecificObject 一无所知,因为它驻留在单独的包基库中。

反过来SpecificObjectHandler驻留在项目A包中,当然知道SpecificObject,需要上面提到的不作用于SpecificObject实例而只依赖BaseObject的常用操作。

由于从std::vector&lt;SpecificObject&gt;std::vector&lt;BaseObject&gt; 的错误转换,代码显然无法编译。

有没有简单优雅的 C++ 14 方法来解决这个问题?或者你对这个问题提出了一个完全不同的模式?

我找到了一些类似问题的答案,但我需要更具体的说明。

谢谢。

【问题讨论】:

  • std::unique_ptr&lt;std::vector&lt;BaseObject&gt;&gt; 与您想要的相反。为了让它工作,你需要一个指向基础对象的指针的向量,或者std::vector&lt;std::unique_ptr&lt;BaseObject&gt;&gt;.
  • 而不是setVector 函数,我建议您创建一个addObject(或类似的)函数来将一个对象添加到现有向量。
  • 不,我想保留一个对象向量,而不是唯一指针。我可以直接传递向量而不是unique_ptr,但问题仍然存在。
  • 首先你几乎从不需要一个指向容器的指针,在这种情况下它真的没有意义。其次,您需要阅读object slicing,而SpecificObject 是-a BaseObject,反之则不然。最后,如果你只有一个 BaseObject 实例,你就不能使用任何类型的多态性,它需要指针或引用才能工作。
  • 我认为如果您向我们询问您尝试使用这样的代码解决的实际问题会更好。你为什么需要它?为什么你认为这样的事情是解决这个问题的唯一可能的方法?也许还有其他可能的解决方案?

标签: c++ templates vector base derived


【解决方案1】:

假设您可以编辑基础库代码,您可以将BaseObjectHandler 定义为模板类

// base_class_library.hpp

template<typename ObjectType>
class BaseObjectHandler
{
    public:

        void setVector(std::unique_ptr<std::vector<ObjectType>>&& v)
        {
            vec = std::move(v);
        }

    protected:
        std::unique_ptr<std::vector<ObjectType>> vec;
};

并继承class SpecificObjectHandler : public BaseObjectHandler&lt;SpecificObject&gt;。现在SpecificObjectHandler 具有指向SpecificObjects 向量的指针,您的代码将编译。

当然,它可能会导致与基库的其他用途发生冲突,但是当您需要旧(您的)版本的BaseObjectHandler 时,您可以将其声明为BaseObjectHandler&lt;BaseObject&gt;。作为价格,您可能会放弃将SpecificObjectHandler 转换为通用BaseObjectHandler 的可能性,但这对您来说可能并不重要。

【讨论】:

  • 这是一个很好的答案,谢谢。但这不是我的实际代码,我在这里分享它会相当复杂。从逻辑的角度来看,我不想将一种从 Object(Base 或非 Base)的依赖添加到 BaseObjectHandler 中,因为在我的实际案例中,它不仅仅处理此类对象。还有其他建议吗?
  • 您可以将 vec 内的 BaseObjectHandler 更改为指向 BaseObject 的指针向量(或任何其他老实说的指针)并将它们重铸在 SpecificObjectHandler 内,但您必须存储其他地方的物体。另一种方法,如果SpecificObject 仅通过新函数而不是通过新变量扩展BaseObject,您可以在SpecificObjectHandler 中获取指向BaseObject 的指针并将其重铸为SpecificObject*,但这仅适用于非常特殊的情况案子。我没有想到其他任何事情。
猜你喜欢
  • 1970-01-01
  • 2011-08-03
  • 2020-08-30
  • 2012-12-17
  • 1970-01-01
  • 2011-02-01
  • 2011-06-02
  • 1970-01-01
相关资源
最近更新 更多