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

1 ... 41 42 43 [ 44 ] 45 46 47 ... 96


void submit Job(const PrintJob& job);

void reset () ;

void performSelfTest();

friend Printers thePrinter(); private:

Printer 0;

Printer(const Printers rhs) ;

Printers thePrinter0 И эта функция тоже.

static Printer p; return p;

} Конец пространства имен.

Если задано пространство имен, то пользователи могут вызывать функцию thePrinter при помощи полного имени (которое включает имя пространства имен):

РгintingStuff::thePrinter().reset() ; PrintingStuff::thePrinter().submitJob(buffer);

HO также мог}гг применить объявление us ing, чтобы записать это более компактно:

using PrintingStuff::thePrinter; Импортировать имя

thePrinter из пространства имен PrintingStuff.

thePrinter О . reset () ; Теперь можно использовать

thePrinterО.submitJob(buffer); thePrinter

как локальное имя.

В реализации функции thePrinter есть две тонкости, достойные отдельного рассмотрения. Во-первых, важно, чтобы единственный объект Printer был статическим в функции, а не в классе. Объект, который является статическим в классе, всегда создается (и уничтожается), даже если он не используется. Если же объект является статическим в функции, то он создается при первом вызове функции, поэтому если она вовсе не вызывается, то и объект не будет создан. (Но тогда при каждом вызове функции придется проверять, нужно ли создавать объект.) Одно из философских оснований, на которых был построен язык C-i-i-, - представление о том, что не стоит платить за вещи, которые не используются, и определение такого объекта, как принтер, в качестве статического в функции является одним из способов придерживаться данного тезиса. Чтобы ваши программы были эффективными, следуйте этому принципу везде, где возможно. Если сделать объект принтера статическим в классе, а не в функции, то обнаружится еще один недостаток такого подхода: не будет известно время инициализации объекта. Вы знаете, что статический элемент функции инициализируется при первом вызове функции в точке определения статического элемента. В случае определения



* В июле 1996 года комитет ISO/ANSI по стандартизации изменил для встраиваемых функций компоновку по умолчанию на внешнюю, поэтому описываемая мной проблема уже устранена, по крайней мере на бумаге. Тем не менее, ваши компиляторы могут еще не соответствовать стандарту, поэтому лучше избегать применения встраиваемых функций со статическими данными.

объекта статическим в классе (или глобальным статическим, если вы додумались сделать это) время инициализации объекта определено не столь точно. Язык С++ гарантирует порядок инициализации статических объектов в определенном транслируемом модуле (то есть блоке исходного кода, компиляция которого дает один объектный файл), но в спецификации языка ничего не говорится о порядке инициализации статических объектов в различных транслируемых модулях. На практике это вызывает бесконечные проблемы, которых нетрудно избежать, если в данной ситуации допустимо определение статических объектов в функции. В нашем примере это возможно.

Вторая тонкость связана с взаимодействием встраивания и статических объектов внутри функций. Посмотрите снова на код версии, в которой функция thePrinter не является членом класса:

Printer thePrinterО {

static Printer р; return р;

Кроме первого вызова (когда должен быть создан объект р) в этой функции выполняется только одна строка - return р;. Если и есть функции, которые могут быть встраиваемыми, то это, похоже, одна из них. Тем не менее, она не объявлена как встраиваемая. Почему?

Вспомним, зачем объект объявляется как статический. Это обычно вызвано тем, что нужна только одна копия данного объекта, не так ли? Теперь вспомним, что означает директива inline: концептуально компиляторы должны заменять вызов функции подстановкой ее тела. Но для функций - не членов класса значение директивы inline этим не ограничивается, потому что для них выполняется внутренняя компоновка.

Обычно не следует беспокоиться о подобных нюансах, главное помнить: функции с внутренней компоновкой (internal linkage) могут дублироваться в программе (то есть код объекта может содержать более одной копии каждой функции с внутренней компоновкой), и такое дублирование включает статические объекты внутри функций. Что получится в результате? Если вы создаете встраиваемую функцию - не член класса, содержащую локальный статический объект, это может привести к созданию более одной копии статического объекта в программе! Поэтому не создавайте встраиваемые функции - не члены класса со статическими данными.*



Но может быть, вы считаете, что создание функции, возвращающей ссылку на скрытый объект, - это не совсем правильный способ ограничить число объектов. Может быть, вы думаете, что лучше просто подсчитать число существующих объектов и, если запрашивается слишком много объектов, генерировать исключение в конструкторе. Другими словами, может быть, вы считаете, что необходимо обрабатывать создание объекта принтера так:

class Printer { public:

class TooManyObjects{}; Класс исключений;

используется, если запрашивается слишком много объектов.

Printer{); -Printer {);

private:

static size t numObjects;

Printer(const Printers rhs); He больше 1 принтера,

поэтому запретить }; копирование.

Идея заключается в том, чтобы использовать переменную NumObjects для отслеживания числа существующих объектов Printer. Ее значение увеличивается на единицу в конструкторе класса и уменьшается на единицу в его деструкторе. Если делается попытка создать слишком много объектов Printer, то генерируется исключение типа TooManyObjects:

Обязательное определение

статического объекта класса.

size t Printer::numObjects = 0;

Printer::Printer()

if (numObjects >= 1) {

throw TooManyObjects();

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

Printer::-Printer() {

выполнить обычное уничтожение объекта; --numObjects;

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



1 ... 41 42 43 [ 44 ] 45 46 47 ... 96

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