首页 > 解决方案 > Base unique_ptr 的向量导致在 emplace_back(new T()) 上进行对象切片

问题描述

我正在尝试将类型作为参数传递给将正确构造对象并将其推送到 unique_ptr 向量的方法,但是创建的对象始终是 Base 对象。使用 emplace_back() 时会发生这种情况,如果我只是实例化对象,同样可以正常工作。

在向量之外构造对象可以正常工作,但是我不确定如何将指针移动到向量之后。

body_parts.hpp

#include <vector>
#include <string>
#include <fmt/core.h>

using namespace std;

namespace uhcr {

class body_part
{
  public:
    string name = "Generic";

    template <class T>
    void add_body_part()
    {
      this->body_parts.emplace_back<T*>(new T());
      fmt::print("{}\n", this->body_parts.back()->name);
    }

  private:
    vector<unique_ptr<body_part>> body_parts;

};

class torso : public body_part
{
  public:
    string name = "Torso";
    
};

}

字符.hpp

#include <string>

#include "components/body_parts.hpp"

using namespace std;

namespace uhcr {
  
class character : public body_part
{
  public:
    string name = "Character";
    
};

}

主文件

#define FMT_HEADER_ONLY
#include <memory>
#include <fmt/core.h>
#include "src/character.hpp"

using namespace fmt;
using namespace uhcr;

void create_human() {
  character human;
  human.add_body_part<torso>();
}

int main(void) {
  create_human();  
  return 1;
}

错误出现在 add_body_part() 处,运行此代码时会打印“通用”。

标签: c++templatesstdvectorunique-ptremplace

解决方案


您的子类中有多个数据成员name。您可能希望将值分配给 中的成员body_part,而不是声明隐藏它的新成员。

class body_part
{
  public:
    body_part() = default;
    string name = "Generic";

    template <class T>
    void add_body_part()
    {
      this->body_parts.emplace_back<T*>(new T());
      fmt::print("{}\n", this->body_parts.back()->name);
    }
  protected:
    body_part(std::string name) : name(name) {}

  private:
    vector<unique_ptr<body_part>> body_parts;

};

class torso : public body_part
{
  public:
    torso() : body_part("Torso") {}
    
};

class character : public body_part
{
  public:
    character() : body_part("Character") {}
    
};

推荐阅读