|
Программирование >> Инициализация объектов класса, структура
void base:: foo( int ival = base default value ) { int real default value = 1024; настоее значение по умолчанию if ( ival == base default value ) ival = real default value; ... Здесь base default value - значение, согласованное между всеми классами иерархии, которое явно говорит о том, что пользователь не передал никакого аргумента. void derived:: foo( int ival = base default value ) { int real default value = 204 8; if ( ival == base default value ) ival = real default value; ... Производный класс может быть реализован аналогично: 17.5.5. Виртуальные деструкторы void doit and bedone( vector< Query* > *pvec ) { ... for ( ; it != end it; ++it ) Query *pq = *it; ... delete pq; В данной функции мы применяем оператор delete: Чтобы функция выполнялась правильно, применение delete должно вызывать деструктор того класса, на который указывает pq. Следовательно, необходимо объявить деструктор Query виртуальным: class Query public: virtual ~Query() { delete solution; } ... Деструкторы всех производных от Query классов автоматически считаются виртуальными. doit and bedone() выполняется правильно. Поведение деструктора при наследовании таково: сначала вызывается деструктор производного класса, в случае pq - виртуальная функция. По завершении вызывается деструктор непосредственного базового класса - статически. Если деструктор объявлен встроенным, то в точке вызова производится подстановка. Например, если pq указывает на объект класса AndQuery, то delete pq; приводит к вызову деструктора класса AndQuery за счет механизма виртуализации. После этого статически вызывается деструктор BinaryObject, а затем - снова статически - деструктор Query. class Query { public: ... protected: virtual ~Query(); ... class NotQuery : public Query { public: ~NotQuery() ; ... В следующей иерархии классов уровень доступа к конструктору NotQuery открытый при вызове через объект NotQuery, но защищенный - при вызове через указатель или ссылку на объект Query. Таким образом, виртуальная функция подразумевает уровень доступа того класса, через объект int main() { Query *pq = new NotQuery; ошибка: деструктор является защищенным delete pq; которого вызывается: class Query public: irtual void eval() = 0; ... чисто виртуальной: }; Реальное разрешение имени eval() происходит при построении отображения слов на вектор позиций. Если слово есть в тексте, то в отображении будет его вектор позиций. В нашей реализации вектор позиций, если он имеется, передается конструктору NameQuery вместе с самим словом. Поэтому в классе NameQuery функция eval() пуста. Однако м1 не можем унаследовать чисто виртуальную функцию из Query. Почему? Потому что NameQuery - это конкретный класс, объекты которого разрешается создавать в приложении. Если бы мы унаследовали чисто виртуальную функцию, то он стал бы абстрактным классом, так что создать объект такого типа не удалось бы. Поэтому мы class NameQuery : public Query { public: virtual void eval() {} ... объявим eval() пустой функцией: }; Для запроса NotQuery от1скиваются все строки текста, где указанное слово отсутствует. Для таких строк в член loc класса NotQuery помещаются все нары (строка, колонка). Наша реализация выглядит следующим образом: Эвристическое правило: если в корневом базовом классе иерархии объявлены одна или несколько виртуальных функций, рекомендуем объявлять таковым и деструктор. Однако, в отличие от конструктора базового класса, его деструктор не стоит делать защищенным. 17.5.6. Виртуальная функция eval() В основе иерархии классов Query лежит виртуальная функция eval() (но с точки зрения возможностей языка она наименее интересна). Как и для других функций-членов, разумной реализации eval() в абстрактном классе Query нет, поэтому мы объявляем ее
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |