Идиомы и стили С++ - [7]

Шрифт
Интервал

. Если Ваш проект действительно серьезный, то без грамотной модели он не существует. Этель Лилиан Войнич никогда бы не дописала свой роман "Овод", если бы с самого начала не задалась моделью: класс ‹солдат› обязательно должен иметь функцию ‹застрелить› экземпляр класса ‹мятежник›, а класс ‹офицер› во-первых, наследует от класса ‹солдат›, во-вторых, может отсортировать набор ‹солдат› в порядке возрастания - построить их на расстрел, в третьих - может и сам пристрелить врага при необходимости. Сильно подозреваю, что в этой модели функция ‹застрелить› является для ‹мятежника› дружественной. Выбирайте друзей правильно!

Шаг 10 - Множественные интерфейсные указатели. Продолжение.

Humpty-Dumpty: "With a name of Your,

You might be any shape, almost!"

L. Carroll. Throw the looking glass.

Сейчас мы поговорим о реализации, но до начала позвольте мне вернуться немного назад и добавить, что есть еще один неплохой способ организации множества интерфейсов. Он выглядит слегка неуклюже, но при известной дисциплине вполне работает: это метод вложенных классов из MFC COM. В самых общих чертах - там применяется явное получение смещения родительского класса от вложенного. Желающие могут посмотреть в MSDN по ключевому слову METHOD_PROLOGUE.

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

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

Для получения интерфейса по объекту проще всего нарисовать конструктор, получающий в качестве аргумента объект:

>// Это объект

>CComplexObject {};

>// Это интерфейс

>CInterface {

>private:

> CComplexObject* co; // Укаэатель на объект

>public:

> CInterface (CComplexObject _co){}; // Это конструктор

>};

Немного подумав, решаем перенести обязанности по порождению интерфейсов на объект. Конструктор интерфейса перекладываем в private, объявляем класс объекта дружественным классу интерфейса, в классе объекта перегружаем операторы преобразования (или русским языком говоря - рисуем операторы преобразования объекта к интерфейсу).

>// Это объект

>class CComplexObject {

> operator CInterface() { return new CInterface(this); } // оператор преобразования

>};


>// Это интерфейс

>CInterface {

>private:

> CComplexObject* co; // Укаэатель на объект

> CInterface (CComplexObject* _co) {} // Это частный конструктор

>};

Думаем еще раз: перенести ответственность за преобразование интерфейсов на специально выделенный smart-указатель, и временно назовем его Super-указателем. Идея с супером просто счастливая - мало того, что не надо изменять объект (код класс объекта), так еще и преобразование упрощается: сначала получим супер по интерфейсу, а потом другой интерфейс по суперу. Да, конечно, два преобразования подряд, но это все же лучше чем в каждом интерфейсе определять преобразование ко всем остальным. Зато интерфейсы ничего не знают друг о друге, им нет нужды, если им известен супер. И потом, поскольку интерфейсы являются простыми smart-ами, надо пожалуй задать функциюшечку, которая бы проверяла - есть ли вообще в природе изрядно подзабытый нами объект. Это место небезуспешно может занять перегруженный оператор operator!().

>// Предварительные объявления классов

>class CComplexObject;

>class CInterface;

>class CSuperObject;


>// Определение объекта пропускаю, это Ваше занятие.

>// Определение супера

>class CSuperObject {

>private:

> CComplexObject* co; // указатель на объект

>public:

> // конструктор супера,

> CSuperObject(CComplexObject* _co): co(_co) {}

> // Живой ли наш объект? Дима! Помаши рукой маме!

> bool operator!(){ return co==NULL; }

> // преобразование к интерфейсу

> operator CInterface();

>}


>// Это интерфейс

>CInterface {

>private:

> CComplexObject* co; // Укаэатель на объект

> CSuperObject* cs; // указатель на супер

> CInterface (CComplexObject* _co) {} // Это частный конструктор

>public:

> bool operator!(){ return co==NULL; } //проверка на существование объекта

> operator CSuperObject (); //преобразование к суперу

>};

Ну все, с этой темой я закругляюсь, но думаю, что идея понятна. Комбинации умных, ведущих, интерфейсных указателей, наследование смартов от абстрактных базовых классов, наследование смартов и указываемых объектов от одних и тех же базовых классов позволяют Вам достичь удивительной гибкости. Помните, как Шалтай-Болтай говорил Алисе "с таким именем ты можешь оказаться кем угодно… просто КЕМ УГОДНО!"? Мы лучше. Мы оказываемся кем угодно, когда угодно, и по собственному желанию.

Напоследок прописная истина для тех, кто не знает: общие определения полиморфизма, наследования, инкапсуляции, понимание перегрузки операторов, перегрузки и переопределения функций, абстрактных классов, виртуальных и чистых виртуальных функций, конструкторов и деструкторов


Еще от автора Альберт Махмутов
Человек! Чего же ты хочешь, скажи!

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


И всё-таки люди созданы для счастья

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


Рекомендуем почитать
Pro Git

Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.


Java 7

Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.


MFC и OpenGL

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


Симуляция частичной специализации

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


Обработка событий в С++

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


Питон — модули, пакеты, классы, экземпляры

Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.