Как написать дескрипторы для классов, которые не имеют члена clone ()? - PullRequest
1 голос
/ 29 августа 2010

Я следую примеру в Ускоренный C ++ и пишу простой класс Handle, который будет действовать как умный указатель. При этом используется идиома virtual ctor с использованием виртуальной функции clone(). Все идет нормально. Но что делать, если я хочу использовать мой Handle для классов, которые я не контролирую и которые не предоставляют clone()?

Метод, предложенный в книге, заключается в создании глобальной clone функции и использовании специализации шаблона (что-то, что я вижу впервые), чтобы при вызове clone() с определенным аргумент, можно написать код для обработки этого случая.

Мой вопрос : это означает, что мне нужно написать clone() версию для каждого типа класса, с которым, как я предполагаю, мой пользователь может использовать Handle Это кажется довольно сложным! Есть ли более элегантный и / или простой способ решить эту проблему? Как это возможно, что такие вещи, как auto_ptr или boost :: shared_ptr могут обеспечить эту функциональность без утомительных clone() определений?

Для полноты вот моя реализация класса Handle:

template <class T> class Handle
{
public:
    Handle() : p(0) {}
    Handle(T* t) : p(t) {}
    Handle( const Handle& s ) :p(0) { if (s.p) p = s.p->clone(); }
    const Handle& operator=( const Handle& );
    ~Handle() { delete p; }

    operator bool() { return p; }

    T& operator*() { if (p) return *p; else throw std::runtime_error("Handle not bound"); }
    T* operator->() { if (p) return p; else throw std::runtime_error("Handle not bound"); }
private:
    T* p; 
};

Спасибо!

1 Ответ

2 голосов
/ 29 августа 2010

Решение этой проблемы - просто не писать Handle s для таких классов. Нет. Действительно.

auto_ptr (устарело в C ++ 11) никогда не нужно клонировать базовый объект, потому что auto_ptr никогда не копирует объект. auto_ptr имеет только одну копию объекта, и когда копируется auto_ptr, управление объектом передается - этот объект не копируется.

unique_ptr никогда не нужно клонировать базовый объект, потому что существует только один unique_ptr, которому принадлежит объект. unique_ptr не может быть скопирован и только подвижен.

shared_ptr никогда не нужно клонировать, потому что он также всегда контролирует только одну копию объекта. Копирование shared_ptr только увеличивает счетчик ссылок, и этот единственный объект уничтожается, когда счетчик ссылок равен нулю.

В общем, если нет способа глубокого копирования ресурса, которым управляет ваш класс, то вы просто должны сделать класс не копируемым. Если клиентам необходимо передать ссылки на ваш класс, они могут сами поместить класс в auto_ptr, unique_ptr или shared_ptr.

...