С++ - язык, который изучается постепенно. Самомодификация и переходимость
                   Справочники Всё для создания сайта

Ссылки


Home
Бизнес
Справочники
Советы







Материалы книги получены с http://www.itlibitum.ru/

Самомодификация и переходимость

Невидимый ведущий указатель, как и любой умный указатель, может интерпретироваться как

переходный тип. Если просто заменить указываемый объект каким-нибудь производным классом, вы фактически изменяете тип всей видимой клиенту комбинации. На этом основано решение проблемы оператора +=, которая требует самомодификации левого операнда, а также возможного оперативного изменения типа «на ходу». Если правый операнд Complex складывается с левым операндом Integer, тип левого операнда приходится менять.

// В файле number.h

class NBase; // Клиентам об этом ничего знать не нужно

class Number {

protected:

Number(const Number&) {}

Number() {}

public:

virtual NBase& AddTo(const NBase&) = 0;

virtual Number& operator+(const Number&) = 0;

// И т.д.

};

// В файле number.cpp

class Integer;

class Real;

class PNumber : public Number {

private:

NBase* number;

protected:

virtual NBase& AddTo(const NBase& n) const

{ return number->AddTo(n); } // #2

public:

PNumber(NBase* n) : number(n) {}

virtual Number& operator+(const Number& n) const

{

number = &(n.AddTo(*number)); // #1 - замена

return *this;

}

};

class NBase : public Number {

// Промежуточный базовый класс

// Традиционная двойная передача в NBase

public:

virtual NBase& operator+=(const Integer&) const = 0;

virtual NBase& operator+=(const Real&) const = 0;

// И т.д.

virtual NBase& AddTo(const NBase&) const = 0;

virtual Number& operator+(const Number& n) const

{ return Integer(0); } // Заглушка не вызывается

};

class Integer : public NBase {

private:

int value;

protected:

virtual NBase& operator+=(const Integer& i) const

{

if (value + i.value достаточно мало) {

value += i.value;

return *this;

}

else {

ArbitraryPrecisionInteger api(value);

api += i.value;

delete this;

return api;

}

public:

Integer(int i) : value(i) {}

virtual NBase& AddTo(const NBase& n) const

{ return n + *this; } // #3

};

class Real : public NBase { ... };

Все как и раньше, разве что операторы + превратились в +=, а двойная передача теперь проходит через +=(левый, правый) и AddTo(правый, левый), чтобы мы могли различать два порядка аргументов.

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

1. Операторная функция PNumber::operator+=(const Number&) автоматически заменяет

число полученным новым значением.

2. Операторная функция Integer::operator+=(const Integer&) возвращает управление,

если ей не приходится изменять тип; в противном случае после удаления своего объекта она

возвращает новый объект другого типа.

По вполне понятным причинам я назову вторую из этих функций заменяющей. Заменяющие функции обладают одной экзотической (если не выразиться сильнее) особенностью: нельзя рассчитывать, что адрес объекта перед вызовом остается действительным и после вызова. Разумеется, пользоваться этим обстоятельством можно лишь в том случае, если эту логику удастся запрятать в самую глубокую и темную дыру, чтобы никто в нее не сунулся, но если это удается сделать, хлопотные алгоритмы невероятно упрощаются.

Показанный пример надежно работает, пока PNumber действует как ведущий указатель и пока можно гарантировать, что ни один объект, производный от NBase, не будет существовать без ссылающегося на него PNumber. В нашем случае, когда все прячется в файле .cpp, дело обстоит именно так.

Для такой простой проблемы программа получилась довольно большой. Я не утверждаю, что ваши хлопоты оправдаются во всех проектах. Мое решение в основном предназначено для ситуаций, в которых вы тратите много времени на разработку иерархии классов многократного использования и можете позволить себе потратить время на повышение модульности. Я привел его, поскольку оно соответствует основной идее книги - выжать из С++ все возможное и невозможное и щедро разбросать головоломки, представляющие интерес даже для самых выдающихся экспертов.


Назад    Содержание    Далее    

Home  Создание сайтов  Учебник по записи CD  Справочник Web дизайнера Самоучитель IE PHP и MySQL Компьютерные сети С++ E-mail me

Copyright 2007. Климов Александр. All Right Reserved.
Hosted by uCoz