Идиомы и стили С++ (Махмутов) - страница 3

они не в пример яснее, и компилятор укажет вам, что вы тормоз, если тормознете. А в Плюсах компилятор просто скроет функции, которые вы переопределите неправильно. Ну мы ему отомстим.

В C++ мы можем перегрузить почти все операторы, за исключением нескольких. Во всяком случае, оператор -› перегружается, и это имеет значение крайне важное. Кстати, он называется селектором (member selector). Итак, попробуем:

>#include ‹mem.h›

>class Cthat {

>public:

> void doIt(void){return;};

>};


>class CPthat {

>private:

> Cthat* aThat;

>public:

> CPthat(Cthat* _that=NULL):aThat(_that){}

> ~CPthat() { if (aThat) delete aThat; }

> operator Cthat* () { return aThat;} // Оператор преобразования типа

> CThat* operator-›() { return aThat; }; // Оператор селектора -›

> CPthat operator+(ptrdiff_t _offset) { return CPthat(aThat+_offset); }

>// ^^^^^^^^^

>};


>int main () {

> Cthat* aThat = new Cthat;

> aThat-›doSomething();

> CPthat pthat(new Cthat);

> pthat-›doIt(); // Вариант обращения через -›

> ((Cthat*)pthat)-›doIt (); //Вариант обращения через Cthat*

> delete aThat;

> return 0;

>}

Что получилось: Имеем класс Cthat, который может иметь экземпляры, хотя и не имеет наполнения, и может исполнить пустую функцию. (Обратите внимание. Пустой объект имеет размер 1, и если добавить переменную char, то размер будет тот же. Экземпляры пустых объектов существуют, и они различаются.) Имеем класс объекта-указателя CPthat, в котором храним обычный указатель, но доступ к нему ограничиваем, и перегружаем для него операторы:

1. приведения типа Cthat

2. member selector -›.

3. Операторы арифметики указателей. Я указал только один, сложение.

Идея ясная. Нужно переопределить все восемь, или не переопределять их вовсе. Вопрос в том, направлен ли Ваш указатель на массив, или нет. Во всяком случае, не спешите с этим. Да, и в Ваших плюсах скорее всего тип ptrdiff_t надо заменить на ptr_diff. Я просто дома на BC3.1 все проверяю.

Что здесь хорошего? Мы получили класс объектов-указателей, которые можно смело применять вместо настоящих. Деструктор ~CPthat() уничтожает указуемый объект, поскольку сам по себе последний не имеет имени, и без своего указателя утрачивает идентичность. Проще говоря, останется в нашей памяти навечно, как герой. Ну можно конечно вызывать деструктор и явно, а что? Вот так:

>pthat-›~Cthat();

Тогда удаление уберите из деструктора указателя.

Напоследок сделаем очевидный шаг - сделаем умный указатель параметризированным классом.

>template ‹class T›

>class SmartPointer {

>private:

> T* tObj;

>public:

> SmartPointer(T* _t=NULL):tObj(_t);

> ~SmartPointer(){ if (tObj) delete tObj; }