Шаг 11 - Нетривиальное конструирование объектов.
Шаг 11 - Нетривиальное конструирование объектов.
В прошлом шаге мы уже столкнулись с ситуацией, когда явное конструирование объектов нежелательно. Выход в таком случае - убрать конструкторы из открытой части объявления. Возможны два варианта - если Вы планируете наследование от этого класса, то конструкторы перемещается в защищенную часть:
CClass {
protected:
CClass () {}
};
А если Вы еще хотите так же и запретить наследование, то конструкторы перемещаются в закрытую часть объявления:
CClass {
private:
CClass () {}
};
Но как же тогда их вообще создавать, если их конструкторы недоступны? Да ясно как, ведь сам вопрос неверен: конструкторы не недоступны, они доступны, да только не для всех. Мы же как-то уже замечали, что класс по определению имеет несколько интерфейсов для разных клиентов, и помним, что самый полный, самый неограниченный интерфейс класс имеет для себя и для своих друзей. Следовательно, производящая функция-член класса или дружественная функция может свободно штамповать экземпляры класса и размещать где угодно, кроме стека; функция-член класса должна быть кроме того статической (то есть независимой от экземпляров), иначе в ней нет смысла.
// Вариант 1: производящая функция-член.
CClass {
public:
static CClass* factory (void);
private:
CClass () {}
};
CClass* CClass::factory(void) { return new CClass(); }
// Где-то в коде
CClass* cc = CClass::factory(void);
// Вариант 2. Дружественная функция.
CClass {
friend CClass* factory (void);
private:
CClass () {}
};
// Дружественная Функция, создающая экземпляры класса.
CClass* factory (void) {
return new CClass;
}
// Где-то в коде
CClass* cc = factory(void);
Вы видите, что разницы между двумя вариантами практически нет? Единственно, что дружественная функция лежит вне области видимости класса. Но она фактически является элементом его интерфейса! Именно это наблюдение позволило Мейерсу сделать несколько неожиданный вывод: дружественные функции могут улучшать инкапсуляцию класса! Не знаю, как для Вас, но мне пришлось прочитать его статью дважды, а потом еще найти перевод на русский язык, потому как сразу это не в голове не уложилось. Подробности читайте в "С++ Journal", апрель 2000 года.
Желая продолжить изыскания в области ограничения конструирования, зададим вопрос: А можно ли совсем запретить конструирование экземпляров класса, даже для друзей и для статических функций? Ответ: Да. Можно. Нужно сделать как минимум одну функцию чистой виртуальной (pure virtual). Для этого есть специальный синтаксис:
virtual void f(void)=0;
В этом случае компилятор не может создать для класса виртуальную таблицу, и соответственно не может создать экземпляр.
Вернемся опять к статической функции. Статическую функцию класса можно вызвать двумя способами - указав либо имя класса, либо через экземпляр класса.
CClass* cc1 = CClass::factory(void);
CClass* cc2 = cc1-›factory(void); // Вызов производящей функции
// Не знаю, откуда мы его берем, но это стековый экземпляр
CClass cc3;
CClass* cc4 = cc3.factory(void); // Еще один вызов производящей функции
Тут-то и делается самый прикол. Мы делаем виртуальный конструктор: виртуальную производящую функцию:
CClass {
public:
// Теперь виртуальная, а не статическая.
virtual CClass* factory (void);
// Конструктор делаем для простоты открытым,
// поскольку все-таки нам нужен
// базовый способ получения экземпляров
CClass () {}
};
CClass* CClass::factory(void) { return new CClass(); }
// Где-то в коде
CClass* cc = new CClass();
// Виртуальное конструирование!!!
CClass* cc1 = cc-›factory(void);
Думаю, что на этом следует закончить этот шаг. К конструированию объектов мы будем возвращаться еще не раз… но не сегодня.
Примером производящих функций являются макросы DECLARE_SERIAL, IMPLEMENT_SERIAL, DECLARE_DYNCREATE, IMPLEMENT_DYNCREATE в MFC. Они конечно сложнее и делают много чего еще, но в конечном итоге это замазанные макросом производящие функции.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
Глава 6 Конструирование форм
Глава 6 Конструирование форм 6.1. Элемент FORM6.2. Создание полей формыЧто главное в Интернете? Его интерактивность. Можно общаться с посетителями сайта и получать от них отзывы о работе – такое взаимодействие всегда полезно и интересно. Создатели сайта узнают, насколько он
Защита объектов ядра и приватных объектов
Защита объектов ядра и приватных объектов Многие объекты, такие как процессы, потоки или мьютексы, являются объектами ядра (kernel objects). Для получения и установки дескрипторов безопасности ядра используются функции GetKernelObjectsSecurity и SetKernelObjectsSecurity, аналогичные функциям защиты
Конструирование модулей
Конструирование модулей Введение Эта обучающая серия обещает стать возможно одной из самых долгоиграющих мини-серий в истории, конкурирующей только с задержкой на Томе IV Кнута. Начатая в 1988, эта серия вошла в четырехлетнюю паузу в 1990, когда «заботы мира сего», изменения
Построение объектов
Построение объектов Моделирование с использованием стандартных объектов – основной метод создания моделей. Простые формы являются основой для создания сложных сетчатых оболочек, например сферу можно представить как заготовку для создания яблока, а немного изменив
Выделение объектов
Выделение объектов Только что созданный объект является выделенным. Понять, что объект является выделенным, очень просто: в окнах Тор (Вид сверху), Front (Вид спереди), Left (Вид слева) он всегда имеет контур белого цвета, в окне проекции Perspective (Перспективный вид) выделенный
Копирование объектов
Копирование объектов Представьте, что мы строим кровать, которая стоит на четырех ножках-опорах. Мы построили одну ножку, расположили ее в нужном месте, теперь необходимо построить еще одну. Каждый раз строить новую нерационально, особенно если это не просто ножка, а
Скрытие объектов
Скрытие объектов Чтобы облегчить управление сложными сценами, используют скрытие объектов. Это ускоряет отрисовку объектов в окнах проекций, в результате чего возрастает скорость работы. Скрытые объекты невидимы, и их нельзя выделить.Скрыть объекты можно несколькими
Выравнивание объектов
Выравнивание объектов В процессе работы часто приходится перемещать объекты, выравнивая их положение относительно друг друга. Например, при создании сложной модели, детали которой моделируются отдельно (допустим, люстры с подвесками в классическом стиле), на
17.4. Конструирование базового и производного классов
17.4. Конструирование базового и производного классов Напомним, что объект производного класса состоит из одного или более подобъектов, соответствующих базовым классам, и части, относящейся к самому производному. Например, NameQuery состоит из подобъекта Query и объекта-члена
Конструирование Splitter
Конструирование Splitter У меня есть форма с расположенными на ней компонентами TreeView и Memo. Значение свойства align обоих компонентов позволяет им занимать всю форму. Я хотел бы расположить между ними движок типа Splitter, пропорционально меняющий их размеры (один шире, другой
Конструирование макетов
Конструирование макетов Данный режим служит для построения макетов корпусной мебели (обычных кухонных шкафов).Выберите в раскрывающемся списке Раздел пункт Конструирование макетов и нажмите кнопку ОК – откроется соответствующее окно (рис. 7.2). Рис. 7.2. Окно
Копирование объектов
Копирование объектов Команда COPY осуществляет копирование объектов. Она вызывается из падающего меню Modify ? Сору или щелчком на пиктограмме Сору на панели инструментов Modify.Запросы команды COPY:Select objects: – выбрать объектыSelect objects: – нажать клавишу Enter для завершения выбора
анализы: Конструирование трудностей "для мозгов"
анализы: Конструирование трудностей "для мозгов" Конструирование трудностей "для мозгов"Автор: Александр ПоддьяковОпубликовано в журнале "Компьютерра" N27-28 от 22 июля 2008 годаБорьба с трудностями имеет давнюю историю — продолжительностью в эволюцию жизни на Земле. И по
Объектно-ориентированное конструирование ПО
Объектно-ориентированное конструирование ПО У нас уже накоплено достаточно оснований, чтобы попытаться определить ОО-конструирование ПО. Это будет лишь первый набросок, более конкретное определение последует в следующей лекции.ОО-конструирование ПО (определение 1)
Конструирование объектно-ориентированного ПО
Конструирование объектно-ориентированного ПО Мы уже давали определение конструирования ОО-ПО: будучи весьма общим, оно представляет метод следующим образом: "основывать архитектуру всякой программной системы на модулях, полученных из типов объектов, с которыми