Читаем Программирование. Принципы и практика использования C++ Исправленное издание полностью

  #include "my_windows_header.h"

#else

  #include "my_linux_header.h"

#endif

Теперь, если кто-нибудь уже определил WINDOWS до того, как компилятор увидел этот код, произойдет следующее:

#include "my_windows_header.h"

В противном случае будет включен другой заголовочный файл.

#include "my_linux_header.h"

Директива #ifdef WINDOWS не интересуется, что собой представляет макрос WINDOWS; она просто проверяет, был ли он определен раньше.

В большинстве крупных систем (включая все версии операционных систем) существуют макросы, поэтому вы можете их проверить. Например, можете проверить, как компилируется ваша программа: как программа на языке C++ или программа на языке C.

#ifdef __cplusplus

  // в языке C++

#else

 /* в языке C */

#endif

Аналогичная конструкция, которую часто называют стражем включения (include guard), обычно используется для предотвращения повторного включения заголовочного файла.

/* my_windows_header.h: */

#ifndef MY_WINDOWS_HEADER

#define MY_WINDOWS_HEADER

  /* информация о заголовочном файле */

#endif

Директива #ifndef проверяет, не было ли нечто определено раньше; например, #ifndef противоположна директиве #ifdef. С логической точки зрения эти макросы, использующиеся для контроля исходного файла, сильно отличаются от макросов, использованных для модификации исходного кода. Просто они используют одинаковый базовый механизм для выполнения своих функций. 

<p id="AutBody_Root565"><strong>27.9. Пример: интрузивные контейнеры</strong></p>

Контейнеры из стандартной библиотеки языка С++, такие как vector и map, являются неинтрузивными; иначе говоря, они не требуют информации о типах данных, использованных как их элементы. Это позволяет обобщить их для практически всех типов (как встроенных, так и пользовательских), поскольку эти типы допускают операцию копирования. Существует и другая разновидность контейнеров — интрузивные контейнеры (intrusive container), популярные в языках C и C++. Для того чтобы проиллюстрировать использование структур, указателей и свободной памяти, будем использовать неинтрузивный список.

Определим двухсвязный список с девятью операциями.

void init(struct List* lst); /* инициализирует lst пустым */

struct List* create;       /* создает новый пустой список

                                в свободной памяти */

void clear(struct List* lst);   /* удаляет все элементы списка lst */

void destroy(struct List* lst); /* удаляет все элементы списка lst,

                                   а затем удаляет сам lst */

void push_back(struct List* lst, struct Link* p); /* добавляет

                                  элемент p в конец списка lst */

void push_front(struct List*, struct Link* p); /* добавляет элемент p

                                  в начало списка lst */

/* вставляет элемент q перед элементом p in lst: */

void insert(struct List* lst, struct Link* p, struct Link* q);

struct Link* erase(struct List* lst, struct Link* p); /* удаляет

                                         элемент p из списка lst */

/* возвращает элемент, находящийся за n до или через n узлов

   после узла p:*/

struct Link* advance(struct Link* p, int n);

Мы хотим определить эти операции так, чтобы их пользователям было достаточно использовать только указатели List* и Link*. Это значит, что реализации этих функций можно кардинально изменять, не влияя на работу их пользователей. Очевидно, что выбор имен был сделан под влиянием библиотеки STL. Структуры List и Link можно определить очевидным и тривиальным образом.

struct List {

  struct Link* first;

  struct Link* last;

};

struct Link { /* узел двухсвязного списка */

  struct Link* pre;

  struct Link* suc;

};

Приведем графическое представление контейнера List:

Перейти на страницу:

Похожие книги

97 этюдов для архитекторов программных систем
97 этюдов для архитекторов программных систем

Успешная карьера архитектора программного обеспечения требует хорошего владения как технической, так и деловой сторонами вопросов, связанных с проектированием архитектуры. В этой необычной книге ведущие архитекторы ПО со всего света обсуждают важные принципы разработки, выходящие далеко за пределы чисто технических вопросов.?Архитектор ПО выполняет роль посредника между командой разработчиков и бизнес-руководством компании, поэтому чтобы добиться успеха в этой профессии, необходимо не только овладеть различными технологиями, но и обеспечить работу над проектом в соответствии с бизнес-целями. В книге более 50 архитекторов рассказывают о том, что считают самым важным в своей работе, дают советы, как организовать общение с другими участниками проекта, как снизить сложность архитектуры, как оказывать поддержку разработчикам. Они щедро делятся множеством полезных идей и приемов, которые вынесли из своего многолетнего опыта. Авторы надеются, что книга станет источником вдохновения и руководством к действию для многих профессиональных программистов.

Билл де Ора , Майкл Хайгард , Нил Форд

Программирование, программы, базы данных / Базы данных / Программирование / Книги по IT