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

1 ... 43 44 45 [ 46 ] 47 48 49 ... 96


продолжить обычное создание объекта; ++numObjects ;

Printer * Printer::makePrinter() { return new Printer; }

Если требование того, что при попытке создания слишком большого числа объектов надо генерировать исключение, кажется вам чрезвычайно строгим, вы можете вместо этого возвращать в псевдоконструкторе нулевой указатель. Конечно, тогда клиентам придется проверять указатель перед тем, как работать с ним.

Клиенты используют класс Printer так же, как и любой другой, только вместо настоящего конструктора они должны вызывать псевдоконструктор:

Printer р1; Ошибка! конструктор

по умолчанию - закрытый.

Printer *р2 = Printer::makePrinter(); Нормально,

косвенно вызывает

конструктор по умолчанию.

Printer рЗ = *р2; Ошибка! конструктор

копирования - закрытый.

p2->performSelfTest{); Все остальные функции

p2->reset{); вызываются как обычно.

delete р2; Надо, чтобы избежать

утечки ресурсов; не нужно, если указатель р2 имеет тип auto ptr.

Этот метод применим к любому числу объектов. Вы должны только заменить постоянную 1 на нужное значение, а затем снять запрет на копирование объектов. Например, следующая реализация класса Printer допускает существование до 10 объектов Printer:

class Printer { public:

class TooManyObj ectsO;

Псевдоконструкторы.

static Printer * makePrinter{);

static Printer * makePrinter(const Printers rhs) ;

private:

static size t numObjects;

static const size t maxObjects =10; См. ниже.

Printer О;

Printer(const Printers rhs);

Обязательное объявление статических объектов класса. size t Printer::numObjects = 0;



const size t Printer::maxobjects;

Printer::Printer{)

if (numObjects >= maxObjects) { throw TooManyObj ects () ;

Printer::Printer(const Printers rhs) {

if (numObjects >= maxObjects) { throw TooManyObj ects () ;

Printer * Printer::makePrinter() { return new Printer; }

Printer * Printer::makePrinter(const Printers rhs) { return new Printer (rhs) ; }

He удивляйтесь, если объявление Printer: :maxObjects в определении этого класса компиляторы не примут. В особенности если они будут сообщать об ошибке при присвоении переменной начального значения 10. Возможность присваивать начальные значения статическим элементам, объявленным как const (целочисленных типов, например int, char, enum и т.д.) внутри определения класса была добавлена в язык С++ сравнительно недавно, поэтому некоторые компиляторы еще не позволяют этого. Если ваши компиляторы относятся к ним, вы можете объявить maxObjects как счетчик в закрытом неименованном перечисляемом типе:

class Printer { private:

enum { maxObjects = 10 }; В этом классе

... maxObjects - постоянная,

}; равная 10.

ИЛИ при помощи инициализации постоянного статического объекта как статического элемента не const:

class Printer { private:

static const size t maxObjects; He задано начальное

значение.

Это находится в отдельном файле реализации, const size t Printer::maxObjects = 10;

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



программистами. Если ваши компиляторы поддерживают задание начального значения для статических const элементов в определении класса, вы должны использовать эту возможность.

Базовый класс для подсчета объектов

У вышеописанного метода есть один негативный аспект. Если существует множество классов, подобных классу Printer, число экземпляров которых требуется ограничивать, то вам придется писать один и тот же код снова и снова для каждого из классов. В таком шикарном языке, как C-i-i-, должен быть способ автоматизировать этот процесс. Как же инкапсулировать понятие подсчета числа экземпляров и заключить его в класс?

Это легко сделать, создав базовый класс для подсчета числа экземпляров объекта и сделать такие классы, как Printer, его наследниками, но, оказывается, есть лучшее решение. Можно разработать способ инкапсуляции всего набора для подсчета, под которым я подразумеваю не только функции, управляющие подсчетом экземпляров, но и сам алгоритм подсчета экземпляров. (Вы увидите необходимость аналогичного приема при рассмотрении счетчика ссылок в правиле 29.)

В классе Printer счетчиком является статическая переменная NumObj ects, поэтому вам нужно поместить эту переменную в класс счетчика экземпляров. Вы должны быть также уверены, что каждый из классов, число экземпляров которых подсчитывается, имеет отдельный счетчик. Применение шаблона класса счетчика позволяет автоматически создавать соответствующее число счетчиков: можно сделать счетчик статическим элементом классов, образованных на основе этого шаблона:

template<class BeingCounted>

class Counted {

public:

class TooManyObjects{}; Для генерации исключений,

static int objectCount {) { return numObjects; } protected:

Counted 0;

Counted(const Counted& rhs) ; -CountedO { -numObjects; } private:

static int numObjects;

static const size t maxObjects;

void initO ; Чтобы избежать дублирования

}; / / кода конструктора.

template<class BeingCounted> Counted<BeingCounted>::Counted() { initO ; }

template<class BeingCounted>

Counted<BeingCounted>::Counted(const Counted<BeingCounted>&) { init(); }



1 ... 43 44 45 [ 46 ] 47 48 49 ... 96

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