|
Программирование >> Оптимизация возвращаемого значения
virtual ostreamSc print{ostream& s) const = 0; class TextBlock: public NLComponent { public: virtual ostreamSc print(ostream& s) const; class Graphic: public NLComponent { public: virtual ostreamSc print (ostreamSc s) const; inline ostreamSc operator (ostreamSc s, const NLComponentSc c) { return с.print(s); Подобным образом легко создавать функции - не члены класса, действующие как виртуальные. Вначале пишутся виртуальные функции, которые выполняют работу, а затем функция - не член класса, всего лишь вызывающая виртуальную функцию. Чтобы избежать расходов на вызов функции в этом синтаксическом фокусе, нужно сделать невиртуальную функцию встроенной. Теперь, когда вы знаете, как сделать, чтобы функции - не члены класса работали как виртуальные в случае одного аргзшента, вы можете поинтересоваться, можно ли сделать то же самое для нескольких аргументов. Да, но это непросто. Насколько непросто? Обратитесь к правилу 31, которое посвящено данному вопросу. Правило 26. Ограничивайте число объектов в классе Иногда для эффективной работы компьютера приходится ограничивать число используемых объектов. Например, в вашей системе есть только один принтер и вы хотите, чтобы объект принтера был единственным. Или вы можете выдать только 16 файловых дескрипторов, поэтому вы хотите быть уверены, что существует не больше 16 объектов файловых дескрипторов. Как можно сделать это? Как ограничить число объектов? Если взять за образец доказательство при помощи математической индукции, следовало бы начать с п = 1, а затем действовать по индукции. К счастью, это не доказательство. Более того, будет поучительным начать с п = О, чтобы узнать, как можно предотвратить создание экземпляров объектов? Разрешение создания нулевого числа объектов или одного объекта При каждом создании экземпляра объекта будет вызван его конструктор. В этом случае проще всего предотвратить создание объектов определенного класса, объявив его конструкторы как закрытые: class CantBelnstantiated { private: CantBelnstantiated{); CantBeInstantiated(const CantBelnstantiatedSt) Запретив при этом создание объектов, можно избирательно ослаблять заданное ограничение. Если, например, вы хотите создать класс для принтеров, но желаете видеть в своей системе только один принтер, можно инкапсулировать объект принтера в функции так, чтобы все имели доступ к принтеру, но создавался только один объект: class PrintJob; Предварительное объявление, class Printer { public: void submitJob(const PrintJob& job) ; void reset () ; void performSelfTest{); friend Printers thePrinter(); private: Printer{); Printer(const Printer& rhs) ; Printer& thePrinter0 { static Printer p; Единственный объект принтера, return p; Эта схема состоит из трех компонентов. Во-первых, конструкторы класса Printer являются закрытыми. Это предотвращает создание объектов. Во-вторых, объявляется дружественная к классу глобальная функция thePrinter. Это позволяет функции thePrinter пол5ать доступ к закрытым конструкторам. И наконец, функция thePrinter содержит статический объект Printer. Это означает, что может быть создан только один объект. Код клиента осуществляет взаимодействие с единственным принтером системы при помощи функции thePrinter. Возвращая указатель на объект Printer, функция thePrinter может использоваться везде, где мог бы находиться объект Printer: class PrintJob { public: PrintJob(const strings whatToPrint); string buffer; ... Поместить данные в буфер. thePrinter().reset(); thePrinterO.submitJob(buffer); Вероятно, функция thePrinter покажется вам ненужным добавлением к глобальному пространству имен. Вы можете сказать: Эта глобальная функция больше похожа на глобальную переменную, а использовать глобальные переменные плохо, и я бы предпочел, чтобы все функции, связанные с принтером, находились внутри класса Printer . Я не буду спорить с теми, кто считает, что это плохо. Можно сделать функцию thePrinter статической функцией - членом класса Printer. Это также устраняет необходимость объявления ее как friend, что многие считают нелогичным. При использовании статической функции-члена класс Printer примет следующий вид: class Printer { public: static Printers thePrinter(); private: Printer() ; Printer(const Printers rhs); Printers Printer::thePrinter0 { static Printer p; return p; Клиентам придется вызывать принтер более многословно: Printer::thePrinter().reset(); Printer::thePrinter().submitJob(buffer); Другой подход заключается в том, чтобы переместить класс Printer и функцию thePrinter из глобального в отдельное пространство имен (namespace). Пространства имен являются сравнительно недавним дополнением языка С++. Все, что можно объявить глобально, можно объявить и в отдельном пространстве имен, включая классы, структуры, функции, переменные, объекты, определения типов и т.д. Выделение в отдельное пространство имен не изменяет поведение всех этих субстанций, но позволяет предотвратить конфликты между различными пространствами имен. Поместив класс Printer и функцию thePrinter в отдельное пространство имен, вы можете не беспокоиться о том, что кто-либо еще выберет имена Printer и thePrinter; отдельное пространство имен предотвращает конфликты имен. Синтаксически пространства имен очень похожи на классы, но в них нет открытых, закрытых или защищенных разделов; вся информация является открытой. Вы можете поместить класс Printer и функцию thePrinter в пространство имен PrintingStuf f следующим образом: namespace PrintingStuff { class Printer { Этот класс находится public: в пространстве имен PrintingStuf f.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |