Cloneable
От: ST1 Россия  
Дата: 21.04.13 08:55
Оценка:
Не претендуя на новизну, больше на новичков

Оператор копирования и паттерн Прототип

Интуитивное копирование

Заводим общую функцию для конструктора копирования и оператора присваивания:

class C {
public:
    C(const C &rhs) {
        CopyFrom(rhs);
    }
 
    C &operator = (const C &rhs) {
        CopyFrom(rhs);
        return *this;
    }
 
    void CopyFrom(const C &rhs) {
        //копируем данные
    }
};


Безопасное копирование

"В каждой функции следует собрать весь код, который может генерировать исключения, и выполнить его отдельно, безопасным с точки зрения исключений способом. Только после этого, когда вы будете знать, что вся реальная работа успешно выполнена, вы можете изменять состояние программы (а также выполнять другие необходимые действия, например, освобождение ресурсов) посредством операций, которые не генерируют исключений." [Герб Саттер, с. 122]
Соответствующая реализация "copy and swap" следует идиоме RAII (получение ресурса есть инициализация) [Мейерс, правило 13] и требует реализации конструктора копирования и функции Swap:


class C {
public:
    C(const C &rhs) {
        //код инициализации
    }
 
    C &operator = (const C &rhs) {
        C temp(rhs);
        Swap(temp);
        return *this;
    }
 
    void Swap(C &rhs) throw() {
        //обмениваем указатели
    }
};



Элегантное копирование


template<typename T>
class Cloneable {
public:
    typedef Cloneable<T> baseClass;
 
    Cloneable() {}
 
    explicit Cloneable(const Cloneable &) {}
 
    virtual ~Cloneable() {}
 
    static T *New() {
        return new T;
    }
 
    T &operator = (const T &rhs) {
        if (This() != &rhs) {
            T temp(rhs);
            Swap(temp);
        }
        return *This();
    }
 
    virtual T *Clone() {
        return new T(*This());
    }
 
    virtual void Swap(T &) = 0;
 
    virtual T* This() = 0;
};
 
 
class C : public Cloneable<C> {
public:
    C(const C &rhs) {
        //код инициализации
    }
 
    C *This() {
        return this;
    }
 
    void Swap(C &rhs) throw() {
        //обмениваем указатели
    }
};


Ссылки

Герб Саттер, Решение сложных задач на C++. Изд. Вильямс, 2002.
Скотт Мейерс. Эффективное использование C++. 55 верных советов улучшить структуру и код ваших программ, 2006.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.