|
Программирование >> Оптимизация возвращаемого значения
Образующие эту структуру классы определяются так: template<class Т> Шаблон класса для интеллектуальных class RCPtr { указателей на объекты Т; класс Т public: должен наследовать от класса RCObject. RCPtr(Т* realPtr = 0) ; RCPtr {const RCPtrSc rhs) ; -RCPtr{) ; RCPtrSc operator= {const RCPtrSc rhs) ; T* operator->{) const; TSc operator* 0 const; private: T *pointee; void init(); class RCObject { Базовый класс для объектов public: со счетчиком ссылок. void addReference{); void removeReference(); void markUnshareable(); bool isShareable() const; bool isSharedO const; protected: RCObject{) ; RCObject (const RCObjectSc rhs); RCObjectSc operator= (const RCObjectSc rhs) ; virtual -RCObjectO = 0; private: int refCount; bool shareable; class String { Класс для использования public: прикладными разработчиками. String(const char *value = ); const charSc operator [] (int index) const; charSc operator [] (int index) ; private: Класс для хранения строковых значений struct StringValue: public RCObject { char *data; StringValue(const char *initValue); StringValue(const StringValueSc rhs) ; void init(const char *initValue); -StringValue(); RCPtr<StringValue> value; Этот код в основном суммирует то, что было разработано ранее, поэтому здесь для вас не должно быть сюрпризов. Привнимательном рассмотрении можно увидеть. что к классу String: : StringValue добавлена функция init, но как будет показано дальше, она предназначена для того же, для чего и соответствуюшая функция в классе RCPtr: предотвращает дублирование кода в конструкторах. Открытый интерфейс приведенного класса String значительно отличается от того, который использовался в начале этого раздела. Где конструктор копирования? Где оператор присваивания? Где деструктор? Здесь явно что-то неладно. Нет, все в порядке. Если вы не видите, что это так, приготовьтесь к крещению языком С++. Эти функции вам больше не нужны. Несомненно, копирование объектов String допустимо, и такое копирование будет корректно обрабатывать лежащие в их основе объекты StringValue со счетчиками ссылок, но в классе String не написано ни одной соответствующей строчки. Причина в том, что созданный компилятором конструктор копирования String автоматически вызовет конструктор копирования элемента RCPtr класса String, который и выполнит все необходимые действия над объектом StringValue, включая и подсчет ссылок на него. Вы не забыли, что указатель RCPtr является интеллектуальным? Он создан для обработки подсчета ссылок, и именно это и делает. Он также выполняет присваивание и уничтожение, поэтому писать данные функции для класса String не нужно. Первоначальная цель упражнения состояла в том, чтобы переместить код для подсчета ссылок из класса String в контекстно-независимые классы, где они были бы доступны для использования любым классом. Теперь это сделано (в форме классов RCObject и RCPtr) и отлично работает. Для того чтобы свести все вместе, приведем реализацию класса RCObject: RCObject::RCObject{) : refCount(0), shareable(true) {} RCObject: :RCObject (const RCObjectSc) : refCount(O), shareable(true) {} RCObjectSc RCObject: :operator = (const RCObjectSc) { return *this; } RCObject::-RCObject0 {} void RCObject::addReference0 { ++refCount; } void RCObject::removeReference() { if (-refCount == 0) delete this; } void RCObject::markUnshareable() { shareable = false; } bool RCObject::isShareable() const { return shareable; } bool RCObject::isShared() const { return refCount > 1; } A это реализация класса RCPtr: template<class T> void RCPtr<T>::init() if (pointee == 0) return; if (pointee->isShareable() == false) { pointee = new T(*pointee); pointee->addReference{); template<class T> RCPtr<T>::RCPtr(T* realPtr): pointee{realPtr) { initO ; } template<class T> RCPtr<T>::RCPtr(const RCPtrSc rhs) : pointee(rhs.pointee) { initO; } template<class T> RCPtr<T>::-RCPtr0 { if (pointee)pointee->removeReference0; } template<class T> RCPtr<T>Sc RCPtr<T>: :operator= (const RCPtrSc rhs) { if (pointee != rhs.pointee) { T *oldPointee = pointee; pointee = rhs.pointee; init(); if (oldPointee) oldPointee->removeReference{) ; return *this; template<class T> T* RCPtr<T>::operator->() const { return pointee; } template<class T> TSc RCPtr<T>::operator*() const { return *pointee; } Реализация string: : StringValue выглядит так: void String::StringValue::init(const char *initValue) { data = new char[strlen(initValue) + 1] ; strcpY(data, initValue); String::StringValue::StringValue(const char *initValue) { init(initValue); } String::StringValue::StringValue(const StringValueSc rhs) { init(rhs.data); } String::StringValue::-StringValue() { delete [] data; ) В конце концов, все пути ведут к классу String, который реализован следующим образом: String::String(const char *initValue): value{new StringValue(initValue)) {} const char& String::operator[](int index) const { return value->data[index]; } charSc String: :operator[] (int index)
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |