Материалы книги получены с http://www.itlibitum.ru/
Ведущие указатели
Невидимые указатели чаще всего являются ведущими (то есть между указателем и указываемым объектом существует однозначное соответствие). С момента рассмотрения ведущих указателей прошло немало времени, поэтому я кратко напомню, что нам предстоит сделать для поддержания семантики ведущих указателей в нашей ситуации:
1. Когда указатель уничтожается, должен уничтожаться и указываемый объект.
2. Когда указатель копируется, должен копироваться и указываемый объект.
3. Когда для указателя выполняется присваивание, он изменяется так, чтобы ссылаться на копию указываемого объекта из правой части выражения.
Недостаточно присвоить указываемый объект из правой части указываемому объекту из левой части, поскольку они могут принадлежать к разным классам.
Уничтожение
Деструктор класса-предка должен быть виртуальным, а деструктор указателя должен уничтожать указываемый объект.
class Foo {
public:
virtual ~Foo() {}
};
// В файле foo.cpp
class PFoo : public Foo {
private:
Foo* foo;
public:
virtual ~PFoo() { delete foo; }
};
Копирование
Копирование невидимых ведущих указателей продолжается с того, на чем мы остановились при копировании неведущих указателей. Каждый производный класс должен переопределить функцию
makeClone().
class Foo {
protected:
Foo(const Foo&) {}
public:
virtual Foo* makeClone() = 0; // Для копирования
};
// В файле foo.cpp
class PFoo : public Foo {
private:
Foo* foo;
public:
PFoo(Foo* f) : foo(f) {}
virtual Foo* makeClone() { return new PFoo(foo->makeClone()); }
};
class Bar : public Foo {
protected:
Bar(Bar&); // Конструктор копий
public:
virtual Foo* makeClone();
};
Foo* Bar::makeClone()
{
return new Bar(*this);
}
Наконец мы добрались и до применения настоящего конструктора копий. Указатель создает копию - не только свою, но и указываемого объекта. В свою очередь, указываемый объект перекладывает всю тяжелую работу на свой собственный конструктор копий. Обратите внимание: чтобы это стало возможным, мы сделали конструктор копий Foo защищенным.
Присваивание
Присваивание для невидимых ведущих указателей похоже на присваивание для любых других типов ведущих указателей. И снова мы продолжаем с того места, на котором остановились при присваивании неведущих указателей.
class Foo {
public:
virtual Foo& operator=(const Foo&);
};
// В файле foo.cpp
class PFoo : public Foo {
private:
Foo* foo;
public:
virtual Foo& operator=(const Foo& f)
{
if (this == &f) return *this;
delete foo;
foo = f.foo->makeClone();
return *this;
}
};
Foo& Foo::operator=(const Foo&)
{
return *this;
}
Назад Содержание Далее
|