【问题标题】:Assignment operator and copy constructor for class containing base class pointer to derived templated class包含指向派生模板类的基类指针的类的赋值运算符和复制构造函数
【发布时间】:2014-09-23 08:35:40
【问题描述】:

为长标题道歉。我正在尝试为我称为Store 的类编写赋值运算符和复制构造函数。

Store 的用途是保存由std::string 标识的其他结构(例如整数、浮点数),可以从Store 添加/检索。这是通过std::map 实现的,std::string 作为映射中的“键”,特定结构作为映射中的“值”。

Store定义如下:

    class Store {

    public:

      Store() {}

      template <class T>
      const T& get(const std::string& key) const;

      template <class T>
      void put(const std::string& key, const T& value, const bool& overwrite = false);

    private:

      std::map<std::string,FieldBase*> m_data;

    };

其中FieldBase定义如下:

    class FieldBase {

    public:

      FieldBase() {}
      virtual ~FieldBase() {}

    }

FieldBase 派生的一个名为Field 的类定义如下:

    template <class T>
    class Field : public FieldBase {

    public:

      Field(const T& value) : m_value(value) {}

      template <class U>
      Field(const Field<U>& other) : m_value( U(other.m_value) ) {}

      template <class U>
      Field& operator=(const Field<U>& other) 
      { 
        m_value = U(other.m_value);
        return *this;
      }

      virtual ~Field() {}

      const T& get() const { return m_value ; }

     private:

       T m_value;

    };

Store 中的添加和检索功能定义如下。 要检索,请使用 Store::get()

    template <class T>
    const T& Store::get(const std::string& key) const
    {

      std::map<std::string,FieldBase*>::const_iterator it = m_data.find(key);

      if ( it == m_data.end() ) {
        std::cout << "Field with name " << key <<" doesn't exist!" << std::endl;
        throw 0;
      }

      Field<T>* field = dynamic_cast<Field<T>*>(it->second);
      if ( field == 0 ) {
        std::cout << "Field with name " << key << " doesn't have correct type!" << std::endl;
        throw 0;
      }

      return field->get();

    }

再补充一句,使用Store::put()

    template <class T>
    void Store::put(const std::string& key, const T& value, const bool& overwrite)
    {

      std::map<std::string,FieldBase*>::iterator it = m_data.find(key);

      if ( it != m_data.end() ) {
        if ( ! overwrite ) {
          std::cout << "Field with name " << key << " doesn't exist!" << std::endl;
          throw 0;
        }
        else {
          delete it->second;
          it->second = 0;
        }
      }

      Field<T>* field = new Field<T>(value);
      m_data[key] = field;

    }

所以,在描述了类及其交互之后,我终于得出了这个问题:

复制构造函数和赋值运算符应该如何查找Store

显然,应该遍历std::map&lt;std::string,FieldBase*&gt; 并以某种方式通过深度复制对象来填充目标地图,但我的问题是我不知道如何确定隐藏在每个@ 下方的Field 的类型987654343@指针...

    // How should these be implemented ???
    Store::Store(const Store& other); 
    Store& Store::operator=(const Store& other);

非常感谢任何帮助。

【问题讨论】:

标签: c++ templates copy-constructor deep-copy assignment-operator


【解决方案1】:

要实现深拷贝,可以添加抽象函数virtual FieldBase * FieldBase::clone() = 0

实现FieldBase* Field&lt;T&gt;::clone() 然后将返回new Field&lt;T&gt;(*this)

唯一剩下的就是遍历Store::m_data的每个条目并调用it-&gt;second-&gt;clone()

【讨论】:

    【解决方案2】:

    你应该看看克隆模式。

    http://en.wikipedia.org/wiki/Cloning_(programming)

    您所做的是向 FieldBase 添加一个纯抽象成员函数,该函数在最派生类型(字段)中定义。

    所以:

    virtual FieldBase* clone() const = 0; //! This goes in FieldBase
    
    FieldBase* clone() const { return new Field<T>(m_value); } //! This goes in Field
    

    然后在复制构造函数中迭代映射并克隆底层值,然后将它们插入新实例的映射中。

    类似这样的:

    Store(const Store& other)
    {
        typedef std::map<std::string, FieldBase*> StoreMap;
        for (StoreMap::const_iterator it(other.m_data.begin()); it != other.m_data.end(); ++it)
            m_data.insert(std::make_pair(it->first, it->second->clone()));
    }
    

    【讨论】:

      猜你喜欢
      • 2015-10-16
      • 2015-07-28
      • 1970-01-01
      • 1970-01-01
      • 2014-06-25
      • 2012-10-05
      • 2023-03-22
      • 1970-01-01
      • 2014-05-16
      相关资源
      最近更新 更多