Навигация
Главная
Поиск
Форум
FAQ's
Ссылки
Карта сайта
Чат программистов

Статьи
-Delphi
-C/C++
-Turbo Pascal
-Assembler
-Java/JS
-PHP
-Perl
-DHTML
-Prolog
-GPSS
-Сайтостроительство
-CMS: PHP Fusion
-Инвестирование

Файлы
-Для программистов
-Компонеты для Delphi
-Исходники на Delphi
-Исходники на C/C++
-Книги по Delphi
-Книги по С/С++
-Книги по JAVA/JS
-Книги по Basic/VB/.NET
-Книги по PHP/MySQL
-Книги по Assembler
-PHP Fusion MOD'ы
-by Kest
Professional Download System
Реклама
Услуги

Автоматическое добавление статей на сайты на Wordpress, Joomla, DLE
Заказать продвижение сайта
Программа для рисования блок-схем
Инженерный калькулятор онлайн
Таблица сложения онлайн
Популярные статьи
OpenGL и Delphi... 65535
Форум на вашем ... 65535
21 ошибка прогр... 65535
HACK F.A.Q 65535
Бип из системно... 65535
Гостевая книга ... 65535
Invision Power ... 65535
Пример работы с... 65535
Содержание сайт... 65535
ТЕХНОЛОГИИ ДОСТ... 65535
Организация зап... 65535
Вызов хранимых ... 65535
Создание отчето... 65535
Имитационное мо... 65535
Программируемая... 65535
Эмулятор микроп... 65535
Подключение Mic... 65535
Создание потоко... 65535
Приложение «Про... 65535
Оператор выбора... 65535
Реклама
Сейчас на сайте
Гостей: 14
На сайте нет зарегистрированных пользователей

Пользователей: 13,372
новичок: vausoz
Новости
Реклама
Выполняем курсовые и лабораторные по разным языкам программирования
Подробнее - курсовые и лабораторные на заказ
Delphi, Turbo Pascal, Assembler, C, C++, C#, Visual Basic, Java, GPSS, Prolog, 3D MAX, Компас 3D
Заказать программу для Windows Mobile, Symbian

Компьютерный магазин на Turbo Pascal (База данных) + Пояснительная записка
Создание последовательности окон и передвижение окон по экрану на Turbo ...
Моделирование литейного цеха на GPSS + Пояснительная записка

«Стражи» включения
Продолжая развитие нашего проекта со стеком, создадим третий модуль, в котором объект класса TStack будет передаваться в функцию как параметр. Назовем этот файл function.срр (листинг 13.3).

Листинг 13.3. Содержимое файла function.срр
// пока стек не пустой
// выводим число с вершины
// удаляем элемент из стека
void function (TStack &t) { while (!t.empty())
{ cout << "(double *)t.top() << endl:
double *p = (double *)t.pop();
delete p;
}
}



Проблем пока нет, но они появляются при подключении файла к нашей главной программе. Выясняется, что мы должны учитывать порядок следования директив #i nclude, чтобы все работало. Правильный порядок такой:
#include <iostream> using namespace std: #include "TStack.cpp" #include "function.cpp"



Стандартный файл iostream должен быть указан перед файлом function.cpp, так как в функции f () выполняется вывод в стандартный поток. Ранее должен быть включен и файл со стеком, так как функция f () его получает в качестве параметра. Порядок следования файлов TStack.cpp и iostream в данном случае может быть произвольным, но только потому, что в нашем стеке никак не используется стандартный ввод-вывод.
Налицо зависимость файлов друг от друга во время компиляции — ситуация крайне неприятная: мало того, что каждый раз транслируется объединенный текст, так еще мы должны «вручную» отслеживать связи между различными модулями. Это достижимо только для очень небольших программ, состоящих не более чем из пары десятков модулей, а дальше начинаются проблемы.
На ум приходит естественное решение — добавить в модуль function.cpp три первые строки из модуля main.cpp:
#include <iostream> using namespace std; #include "TStack.cpp"



Однако при трансляции тут же выясняется, что класс TStack определен дважды1. По стандарту в программе разрешается иметь несколько определений класса, но в разных единицах трансляции (см. п. п. 3.2/5 в [1]). А у нас получается двойное определение в одной единице — в модуле main.cpp. Действительно, после постановки всех наших файлов (про системные файлы пока умолчим) объединенный модуль main.cpp содержит следующие директивы #include:
#include <iostream> — включает системный файл iostream;
#include "TStack.cpp" в модуле main.cpp — включает класс TStack;
#include "function.cpp" в модуле main.cpp — включает файл function.cpp;
#include "TStack.cpp" в модуле function.cpp — включает класс TStack.



Таким образом, класс TStack оказывается определенным дважды. Справиться с этой проблемой нам опять поможет препроцессор: мы должны определить во включаемом файле «стража» включения. Для этого используется директива #def ine и директивы условной трансляции препроцессора. Обычно это делается так:
// myfile.h
#ifndef MYFILE // страж определен?
#define MYFILE // если нет - определяем
// содержимое файла
#endif // конец #ifndef



Первая строка часто пишется немного по-другому:
#if !defined( MYFILE ) // страж определен?



Однако сути дела это не меняет.
Когда препроцессор обрабатывает первую директиву, имя MYFILE (страж) не определено:
Обратите внимание, что с системным файлом ошибок не возникает!
#include "myfile.h"



Поэтому содержимое файла включается в обработку. Если эта директива встречается еще раз, то страж уже определен и содержимое файла пропускается.
Именно так организованы стандартные файлы, и поэтому не было проблем со стандартным файлом iostream. Например, начало стандартного файла math.h в интегрированной среде Borland С++ Builder 6 выглядит так:
/* math.h
Definitions for the math floating point package. ,
*/ /*
* C/C++ Run Time Library - Version 11.0
* Copyright (c) 1987, 2002 by Borland Software Corporation
* All Rights Reserved. */
/* $Revision: 9.17.2.6 $ */
#ifndef MATH_H // проверка стража
#define MATH_H // определение стража



Как видите, определен страж с именем МАТН_Н. Практически не отличается от
этого файла соответствующий файл системы Visual C++.NET 2003 (пропущены некоторые строки, не относящиеся к делу):

/***
¦math.h - definitions and declarations for math library *
* Copyright (c) Microsoft Corporation. All rights reserved. *
¦Purpose:
* This file contains constant definitions and external subroutine
* declarations for the math subroutine library.
* [ANSI/System V] *
* [public] ¦
* * * * /
#ifndef _INC_MATH #define _INC_MATH



В этой системе определен страж с именем _INC_MATH.
По негласному соглашению имена, определяемые в директиве #def i пе, пишутся прописными буквами — это позволяет по одному виду имени определить, что оно «принадлежит» препроцессору и «работает» только на стадии компиляции.
Наш файл TStack.cpp должен быть таким, как показано в листинге 13.4.

Листинг 13.4. Файл TStack.cpp со стражем
#ifndef __STACK // страж определен?
#define _STACK // определение стража
class TStack {
// определение класса
}:
#endif /* _STACK */ // конец ifndef



Теперь все работает правильно.
Опубликовал Kest January 15 2014 17:08:36 · 3 Комментариев · 6517 Прочтений · Для печати

• Не нашли ответ на свой вопрос? Тогда задайте вопрос в комментариях или на форуме! •


Комментарии
Максим January 15 2014 18:26:00
По сути стражи включения я использую довольно редко в своей работе, но есть моменты, когда их использование вполне оправданно.

По мне так это дополнительные возможности самого языка, которые делают его более динамичным и гибким, особенно, когда требуется грамотная компоновка модулей при компиляции большого проекта.
Николай January 17 2014 14:55:25
Никогда не думал, что подключение файлов и библиотек влияет на работу программы, я файлы всегда подключал в произвольном порядке и ошибок не возникало, видимо при подключении своих файлов, я бы столкнулся со сложностями. Просто необходимо разобраться с препроцессорной обработкой, очень часто где встречалась, а я еще толком не знаю что и как там работает и какие команды за что отвечают, но с вашим сайтом думаю это не проблема! Спасибо, пример помог разобраться!
Илья January 18 2014 11:23:19
Николай, этот сайт вообще кладезь полезной информации, по крайней мере для меня. Мне он нравится потому что: 1 - Большое количество литературы, статей, а самое главное можно спросить совет у людей которые в этом действительно разбираются и понимают. Так что тут можно учиться и искать информацию, литературы предостаточно было бы желание как говориться. Если что-то не понимаешь можно спросить, и тебе подскажут. Мне как новичку в этом деле очень помогает. 2 – Общение. На сайте есть форум там можно найти друзей, которые тоже интересуются программированием или просто обсудить интересные новости с другими людьми.
Добавить комментарий
Имя:



smiley smiley smiley smiley smiley smiley smiley smiley smiley
Запретить смайлики в комментариях

Введите проверочный код:* =
Рейтинги
Рейтинг доступен только для пользователей.

Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.

Нет данных для оценки.
Гость
Имя

Пароль



Вы не зарегистрированны?
Нажмите здесь для регистрации.

Забыли пароль?
Запросите новый здесь.
Поделиться ссылкой
Фолловь меня в Твиттере! • Смотрите канал о путешествияхКак приготовить мидии в тайланде?
Загрузки
Новые загрузки
iChat v.7.0 Final...
iComm v.6.1 - выв...
Visual Studio 200...
CodeGear RAD Stud...
Шаблон для новост...

Случайные загрузки
VFW
Indy in Depth Глу...
PDPcheck
C++ Builder в за...
Базы данных в Инт...
Искусство програм...
Панель статистики...
Ics
mp3tag
PHP5. Профессиона...
AJAX и PHP. разра...
Обучение Borland ...
Strawberry Prolog...
PHP: Полезные приемы
База Allsubmitter...
Профессиональное ...
Calendar
index.php + мод ...
Мод "проверочный ...
CS:Source - монит...

Топ загрузок
Приложение Клие... 100793
Delphi 7 Enterp... 98016
Converter AMR<-... 20298
GPSS World Stud... 17059
Borland C++Buil... 14239
Borland Delphi ... 10373
Turbo Pascal fo... 7390
Калькулятор [Ис... 6080
Visual Studio 2... 5228
Microsoft SQL S... 3674
Случайные статьи
Ввод и вывод широк...
Аэродинамическое м...
Ленивая реализация
Решение задачи, ис...
Объединенные связи...
Функции
СУБД mySQL
Иконка в адресной ...
Процедура обратног...
Результаты работы...
Фил ьтрация группо...
Играть в игровые а...
Область применения...
Волоконно-оптическ...
Настройте пакетные...
Дляэтого к каждому...
После неудачи с 12...
Audit System Event...
Качество – заказчи...
Обновление, управл...
Модельное время. С...
CN=Configuration, ...
Обновление набора ...
Установка MPlayer ...
Программа выбирает...
Статистика



Друзья сайта
Программы, игры


Полезно
В какую объединенную сеть входит классовая сеть? Суммирование маршрутов Занимают ли таблицы память маршрутизатора?