简体   繁体   English

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

[英]Assignment operator and copy constructor for class containing base class pointer to derived templated class

Apologies for the long title. 对长标题表示歉意。 I am trying to write an assignment operator and a copy constructor for a class which I call Store . 我试图为我称为Store的类编写一个赋值运算符和一个复制构造函数。

The purpose of Store is hold other structures (eg integers, floats), identified by a std::string , which can be added/retrieved from the Store . Store的目的是保存其他结构(例如,整数,浮点数),这些结构由std::string标识,可以从Store添加/检索。 This is implemented with a std::map , with a std::string as the 'key' in the map and the particular structure as the 'value' in the map. 这是通过std::map ,其中std::string作为映射中的“键”,特定结构作为映射中的“值”。

Store is defined as follows: 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;

    };

where FieldBase is defined as follows: 其中FieldBase的定义如下:

    class FieldBase {

    public:

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

    }

and a class derived from FieldBase called Field is defined as follows: 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;

    };

The functionality in Store to add and retrieve, is defined below. 下面定义了Store中添加和检索的功能。 To retrieve, one uses Store::get() : 要进行检索,可以使用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();

    }

and to add, one uses Store::put() 并添加一个使用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;

    }

So, having described the classes and their interactions, I finally arrive at the question: 因此,在描述了类及其相互作用之后,我终于得出了一个问题:

How should the copy constructor and assignment operator look for Store ? 复制构造函数和赋值运算符应如何查找Store

Obviously, one should iterate over the std::map<std::string,FieldBase*> and somehow fill the target map by deep copying the objects, but my problem is that I don't know how to determine the type of the Field which hides beneath each FieldBase pointer... 显然,应该遍历std::map<std::string,FieldBase*>并通过深度复制对象以某种方式填充目标地图,但是我的问题是我不知道如何确定Field的类型隐藏在每个FieldBase指针下面...

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

Any help is much appreciated. 任何帮助深表感谢。

You should look at the clone pattern. 您应该查看克隆模式。

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

What you do is add a pure abstract member function to FieldBase which is defined in the most derived types (Field). 您要做的是将纯抽象成员函数添加到FieldBase中,该函数在大多数派生类型(字段)中定义。

So: 所以:

virtual FieldBase* clone() const = 0; //! This goes in FieldBase

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

Then in the copy constructor you iterate over the map and clone the underlying values before inserting them in the new instance's map. 然后,在复制构造函数中,您遍历映射并克隆基础值,然后再将其插入新实例的映射中。

Something like this: 像这样:

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()));
}

To implement a deep copy you can add an abstract function virtual FieldBase * FieldBase::clone() = 0 ; 要实现深层副本,您可以添加抽象函数virtual FieldBase * FieldBase::clone() = 0 ;

The implementation FieldBase* Field<T>::clone() would then return new Field<T>(*this) ; 然后,实现FieldBase* Field<T>::clone()将返回new Field<T>(*this)

The only thing left is to iterate over each entry of Store::m_data and call it->second->clone() ; 剩下的唯一事情是遍历Store::m_data每个条目并调用it->second->clone() ;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM