包含指向派生模板类的基类指针的类的赋值运算符和复制构造函数

Posted

技术标签:

【中文标题】包含指向派生模板类的基类指针的类的赋值运算符和复制构造函数【英文标题】: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);

非常感谢任何帮助。

【问题讨论】:

链接到cloning objects in C++ 【参考方案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()));

【讨论】:

以上是关于包含指向派生模板类的基类指针的类的赋值运算符和复制构造函数的主要内容,如果未能解决你的问题,请参考以下文章

cpp(第十三章)

为啥指向基类的派生类指针可以调用派生类成员函数? [复制]

在 C++ 中将派生类对象分配和访问到基类“指向指针”对象

检测基类对指向派生类的引用的分配

从指向基类的指针调用派生类的复制构造?

派生自std :: exception的类的赋值运算符