Материалы книги получены с http://www.itlibitum.ru/
Копирование
Ой! Опять эти проклятые пользователи...
MP<Foo> mpf1; // Создает Foo, на который ссылается указатель
MP<Foo> mpf2 = mpf1; // Неудача!
Пусть знак равенства не вводит вас в заблуждение - здесь происходит конструирование, и эта строка эквивалентна строке MP<Foo> mpf2(mpfl);. Если не перегрузить конструктор копий и разрешить компилятору C++ внести свою лепту, мы получим два ведущих указателя, которые ссылаются на один и тот же объект Foo. По умолчанию конструктор копий, генерируемый компилятором, радостно копирует содержащийся в переменной адрес из старого указателя в новый. Проблема решается относительно просто.
template <class Type>
class MP {
private:
Type* t;
public:
MP(); // Нормальный
MP(const MP<Type>& mp) : t(*(mp.t)) {} // Конструктор копий
};
Этот конструктор копий создает дубликат указываемого объекта, используя для этого конструктор копий указываемого объекта. Получается не очень эффективно, но работает. В некоторых ситуациях, с которыми мы столкнемся позже, лучше вообще запретить копирование. Проще всего для этого объявить конструктор копий закрытым и не назначать ему никаких действий.
template <class Type>
class MP {
private:
Type* t;
MP(const MP<Type>&) : t(NULL) {} // Никогда не будет вызываться
public:
MP();
};
Тем самым мы предотвращаем непреднамеренное копирование в ситуациях вроде следующей:
void f(MP<Foo>);
MP<Foo> mpf;
f(mpf); // Создается временная копия
Для предотвращения копирования также можно воспользоваться дескрипторами, о которых будет рассказано ниже.
Назад Содержание Далее
|