3

我将如何最好地实施这些?我想到了这样的事情:

    using namespace std;

    shape_container
    shape_container::clone_deep () const
    {
        shape_container* ptr = new shape_container();
        copy( data.begin(), data.end(), (*ptr).begin() );
        return *ptr;
    }

    shape_container
    shape_container::clone_shallow () const
    {
        return *( new shape_container(*this) );
    }

成员data定义如下:

    std::map<std::string, shape*> data;

不幸的是,这不起作用。这是编译器错误,我不太了解它们:

    g++ -Wall -O2 -pedantic -I../../UnitTest++/src/ -I./libfglwin/include/ -I. -c shape_container.cpp -o shape_container.o
    /usr/include/c++/4.2.1/bits/stl_pair.h: In member function ‘std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*>& std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*>::operator=(const std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*>&)’:
    /usr/include/c++/4.2.1/bits/stl_pair.h:69:   instantiated from ‘static _OI std::__copy<<anonymous>, <template-parameter-1-2> >::copy(_II, _II, _OI) [with _II = std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >, _OI = std::_Rb_tree_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >, bool <anonymous> = false, <template-parameter-1-2> = std::bidirectional_iterator_tag]’
    /usr/include/c++/4.2.1/bits/stl_algobase.h:315:   instantiated from ‘_OI std::__copy_aux(_II, _II, _OI) [with _II = std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >, _OI = std::_Rb_tree_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >]’
    /usr/include/c++/4.2.1/bits/stl_algobase.h:340:   instantiated from ‘static _OI std::__copy_normal<<anonymous>, <anonymous> >::__copy_n(_II, _II, _OI) [with _II = std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >, _OI = std::_Rb_tree_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >, bool <anonymous> = false, bool <anonymous> = false]’
    /usr/include/c++/4.2.1/bits/stl_algobase.h:401:   instantiated from ‘_OutputIterator std::copy(_InputIterator, _InputIterator, _OutputIterator) [with _InputIterator = std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >, _OutputIterator = std::_Rb_tree_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >]’
    shape_container.cpp:70:   instantiated from here
    /usr/include/c++/4.2.1/bits/stl_pair.h:69: error: non-static const member ‘const std::basic_string<char, std::char_traits<char>, std::allocator<char> > std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*>::first’, can't use default assignment operator
    /usr/include/c++/4.2.1/bits/stl_algobase.h: In static member function ‘static _OI std::__copy<<anonymous>, <template-parameter-1-2> >::copy(_II, _II, _OI) [with _II = std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >, _OI = std::_Rb_tree_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >, bool <anonymous> = false, <template-parameter-1-2> = std::bidirectional_iterator_tag]’:
    /usr/include/c++/4.2.1/bits/stl_algobase.h:268: note: synthesized method ‘std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*>& std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*>::operator=(const std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*>&)’ first required here 

不知何故,这对我来说看起来不必要地复杂。这是真的吗?我可以让它变得更好吗?

顺便说一句,我从 shape 派生的类中有 clone() 方法。也许我可以将它们用于 clone_deep 方法?他们还好吗?它们看起来像这样:

    class shape
    {
        public:
            /* Many methods. */
            virtual shape* clone () const = 0;

        protected:
            colorRGB    color_;
            std::string name_;
    };

    class triangle2d : public shape
    {
        public:
            /* Many methods. */
            triangle2d* clone() const;
        private:
            point3d a_, b_, c_;
    };

    triangle2d*
    triangle2d::clone() const
    {
        return new triangle2d(*this);
    } 
4

4 回答 4

1

通常克隆函数会返回一个指向新实例的指针。您返回的是一个按值的对象,它是从动态分配的实例构造的副本,然后泄漏。

如果你想按值返回,那么你不应该使用new. 例如

shape_container shape_container::clone_shallow () const
{
    return *this;
}

如果该data成员只是一个std::map实例,那么无论如何它将被复制为您的浅克隆的一部分,因此std::copy在深度克隆的情况下不需要这样做,它不会尝试做任何不同的事情。

如果你想做std::copy一个地图,你需要使用一个std::insert_iterator.

不过,我认为clone事后对每个形状做一个可能会更容易。

例如

shape_container shape_container::clone_deep() const
{
    shape_container ret(*this);

    for (std::map<std::string, shape*>::iterator i = ret.data.begin(); i != ret.data.end(); ++i)
    {
        i->second = i->second->clone();
    }

    return ret;
}
于 2009-12-19T10:55:48.413 回答
0

首先,您的示例会泄漏内存,因为您在方法中new使用了 a shape_container,但随后它通过返回值被复制出来。您应该像您的shape示例一样返回指针。

编译器错误看起来在某种程度上与复制有关,因为它抱怨它无法为您生成赋值运算符。再次尝试使用指针,该问题应该会消失。

于 2009-12-19T10:55:31.530 回答
0

如果您对地图进行深拷贝,那么您必须使用深拷贝的所有元素创建一个新的地图。

想想引用计数方法,它会是更好的方法。

于 2009-12-19T11:20:22.363 回答
0

一种选择是将您的形状类型包装在执行对象的深层副本的类型中:

class shape_deep_copy_wrapper {
  // ...
public:
  shape_deep_copy_wrapper (shape * shape)
  : m_my_shape (shape)
  {
  }

  shape_deep_copy_wrapper (shape_deep_copy_wrapper const & rhs)
  : m_my_shape (rhs.m_my_shape.deep_copy ())
  {
  }

  // ...

private:
  shape * m_my_shape;
};

然后用这种类型构造一个地图:

typedef std :: map < shape_deep_copy_wrapper , ... > DeepCopy ;
typedef std :: map < shape* , ... >                  ShallowCopy ;
于 2009-12-21T09:44:19.987 回答