Программирование >>  Оптимизация возвращаемого значения 

1 ... 63 64 65 [ 66 ] 67 68 69 ... 96


Образующие эту структуру классы определяются так:

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)



1 ... 63 64 65 [ 66 ] 67 68 69 ... 96

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика