Бьерн Страуструп.
Язык программирования С++
176
операции, нужно копировать только один раз. Тогда нам потребуется виртуальная функция
размножения для узла выражения.
Как правило "виртуальные конструкторы" являются стандартными конструкторами без параметров или
конструкторами копирования, параметром которых служит тип результата:
class expr {
//
...
public:
expr();
//
стандартный конструктор
virtual expr* new_expr() { return new expr(); }
};
Виртуальная функция new_expr() просто возвращает стандартно инициализированный объект типа
expr, размещенный в свободной памяти. В
производном классе можно переопределить функцию
new_expr() так, чтобы она возвращала объект этого класса:
class conditional : public expr {
//
...
public:
conditional(); // стандартный конструктор
expr* new_expr() { return new conditional(); }
};
Это означает, что, имея объект класса expr, пользователь может создать объект в "точности такого же
типа":
void user(expr* p1, expr* p2)
{
expr* p3 = p1->new_expr();
expr* p4 = p2->new_expr();
//
...
}
Переменным p3 и p4 присваиваются указатели неизвестного, но подходящего типа.
Тем же способом можно определить виртуальный конструктор копирования, называемый операцией
размножения, но надо подойти более тщательно к специфике операции копирования:
class expr {
//
...
expr*
left;
expr*
right;
public:
//
...
// копировать `s' в `this'
inline void copy(expr* s);
// создать копию объекта, на который смотрит this
virtual expr* clone(int deep = 0);
};
Параметр deep показывает различие между копированием собственно объекта (поверхностное
копирование) и копированием всего поддерева, корнем которого служит объект (глубокое копирование).
Стандартное значение 0 означает поверхностное копирование.
Функцию clone() можно использовать, например, так:
void fct(expr* root)
{
expr* c1 = root-
>clone(1); // глубокое копирование
expr* c2 = root->c
lone(); // поверхностное копирование
//
...
}
Являясь виртуальной, функция clone()
способна размножать объекты любого производного от expr
Бьерн Страуструп.
Язык программирования С++
178
Определение последней
функции показывает отличие настоящего копирования в expr::copy() от
полного размножения в expr::clone() (т.е. создания нового объекта и копирования в него). Простое
копирование оказывается полезным для определения более сложных операций копирования и
размножения. Различие между copy() и clone() эквивалентно различию между операцией присваивания
и конструктором копирования ($$1.4.2) и эквивалентно различию между функциями _draw() и draw()
($$6.5.3). Отметим, что функция copy() не является виртуальной. Ей и не надо быть таковой, поскольку
виртуальна вызывающая ее функция clone(). Очевидно, что простые операции копирования можно
также определять как функции-подстановки.
Достарыңызбен бөлісу: