Идиомы и стили С++ | страница 31



// Класс прокси-объекта

>class CProxyInt {

> friend class CInt;

>private:

> int m_i;

>public:

> CProxyInt (int _i): m_i(_i) {}

> int getInt () const { return m_i; }

>};


>// Предыдущий класс инт.

>class CInt {

> friend class CProxyInt;

>private:

> int m_i;

> int m_instance;

> static int iCounter;

>public:

> // Конструктор по умолчанию изменен

> CInt (CProxyInt);

> CInt (const CInt&);

> ~CInt();

> CInt operator+(const CInt&);

> CInt& operator+=(const CInt&);

> CInt& operator= (const CInt&);

>// operator int ();

>};


>int CInt::iCounter = 0;

>// Реализация конструктора, вместо инта стоит прокси

>CInt::CInt (CProxyInt _i=0): m_i(_i.m_i) {

> m_instance = ++iCounter;

> cout‹‹"defa constr " ‹‹ m_instance ‹‹ " "‹‹ m_i ‹‹ endl;

>}

>CInt a(5); // Это компилируется нормально

>CInt a = 5; // А это нет. И все неявные вызовы тоже.

Видите, мы используем технику proxy уже второй раз, но совершенно в другом контексте. Общее то, что proxy применяется в том случае, если мы хотим определить свои законы преобразования типов и классов.

В этом смысле smart-указатель несомненно тоже рroxy, (уменьш. ласк. проксятник, проксятничек).

Шаг 21 - О тщете сущего.

Прежде чем использовать приемы, описанные в предыдущих Шагах, тщательно подумайте - надо ли Вам это? (Примеры с памятью еще и упрощены до свинства, не вздумайте применять в таком виде).

Средний компилятор управляет памятью примерно так, как описано в Шаге 18-19, а именно запрашивает большие куски по необходимости у операционки через calloc(), потом раздает кусочки объектам. Если объект уничтожен, то (по возможности) использует свободное место повторно. Память вернется в операционку только после того, как все объекты в ней уничтожены. Если мы будем писать свой менеджер памяти не почитав теории для начала, то вернее всего ухудшим использование памяти.

Неявные преобразования через конструкторы и операторы преобразований хороши, конечно. Но почему-то пришлось вводить ограничения на них. Чтоб неявно не вызывались. Сколь мне известно, компания Borland/Inprise собирась вводить в Delphi 4/5 перегрузку операторов, но как-то передумала…

Неявные объекты в большинстве случаев не мешают нам жить. Более того, запись в предыдущем шаге, где вызывается 7 конструкторов вместо 4, более читабельна-сопровождабельна, красива, соответствует духу и букве C++ (семантике и синтаксису). Если функция исполняется в программе раз в час, неважно, сколько раз вызовется в ней конструктор - 4 или 44. Скринсавер вообще выполняет море абсолютно бесполезных и сверхсложных вычислений - Вам это мешает?