Поскольку класс GCPtr — это тип указателя, он должен перегружать такие операции с указателями, как: *, -> и операцию индексирования []. Это делается с помощью функций, приведенных далее. Предоставляя возможность перегружать указанные операции и создавать, таким образом, новый тип указателя, они еще и приятно радуют своей простотой. // Возвращает ссылку на объект, на который // указывает этот GCPtr. Т fcoperator*() { return *addr; } // Возвращает адрес, на который указывает. Т *operator->() { return addr;} // Возвращает ссылку на объект //с индексом, заданным i. Т &operator[](int i) { return addrfi]; ) Функция operator* () возвращает ссылку на объект, адрес которого хранится в поле addr активизированного объекта GCPtr, а функция operator-> — адрес, содержащийся в поле addr, функцию operator [] следует использовать только с объектами GCPtr, ссылающимися на массивы. Как уже упоминалось ранее, класс GCPtr не поддерживает арифметические операции с указателями К примеру, ни операция ++, ни операция — не перегружаются в классе GCPtr. Причина в том, что механизм сбора мусора Предполагает, что объект GCPtr указывает на начало выделенного фрагмента памяти. Если указатель объекта GCPtr может быть увеличен, то при сборе мусора адрес, используемый операцией delete, может оказаться неправильным. У вас есть две возможности выполнить действия, включающие арифметическую обработку указателей. Во-первых, если объект GCPtr указывает на размещенный массив, вы можете создать объект iter, который позволит перемещаться по массиву. Эта возможность описана далее. Во-вторых, можно преобразовать указатель типа GCPtr в обычный указатель с помощью функции т *, описанной в классе GCPtr. // Функция преобразования для T *. operator T *() { return addr; } Эта функция возвращает обычный указатель, который ссылается на адрес, хранящийся в поле addr. Ее можно применять следующим образом. GCPtr<double> gcp = new double(99.2); Double *p; P = gcp; // теперь p указывает на ту же память, что и gcp р++; // поскольку р — обычный указатель, его значение можно увеличивать В приведенном примере, поскольку р — обычный указатель, его можно обрабатывать, как любой другой указатель. Конечно, принесут ли подобные манипуляции полезный результат, зависит от содержания вашего приложения. Основная польза от применения функции преобразования заключается в том, что она позволяет использовать объекты GCPtr вместо обычных указателей языка С++ при взаимодействии с созданным ранее кодом, который нуждается в них. Рассмотрим следующий пример. GCPtr<char> str = new char(80); strcpy(str, "this is a test"); couc « str « endl; Переменная str — указатель типа GCPtr, указывающий на данные типа char, — применяется как параметр при вызове функции strcpy. Поскольку эта функция ожидает аргументов типа char *, внутри класса GCPtr автоматически инициируется преобразование в т *, причем в этом случае у т — тип char. То же самое преобразование вызывается автоматически, когда переменная str используется в операторе cout. Таким образом, функция преобразования позволяет объектам GCPtr без каких-либо шероховатостей взаимодействовать с существующими в языке С++ функциями и классами. Помните, что указатель типа т *, возвращаемый функцией преобразования, не участвует в сборе мусора и никак не влияет на него. Следовательно, можно освободить динамически выделенную память, даже если обычный указатель языка С++ к этому моменту все еще на нее ссылается. Итак, используйте преобразование т * нечасто и с умом.
|