Рассмотрим пример программы из раздела Классы в С++. Программа использует простейший класс, объект которого печатает сообщение. Заметьте, что раньше класс был объявлен в одном файле с главной функцией, но такой способ утилизации классов не эффективен, почему, было рассмотрено в разделе Классы в С++. Так вот, теперь объявление класса находится в файле message.h
, а реализация методов класса определена в файле message.cpp
, а classes.cpp
— файл с main()
функцией.
// интерфейс класса, файл: message.h class CppStudio // имя класса { public: // спецификатор доступа void message(); // функция (метод класса) выводящая сообщение на экран }; // конец объявления класса CppStudio
В h-файл помещен только лишь интерфейс класса, далее h-файл будет модифицирован с целью предотвращения ошибки многократного включения заголовочных файлов.
// реализация класса CppStudio, файл: message.cpp #include "stdafx.h" // связываем интерфейс класса с его реализацией #include "message.h" // подключаем прототип оператора cout #include <iostream> void CppStudio::message() // функция (метод класса) выводящая сообщение на экран { std::cout << "website: cppstudio.com\ntheme: Classes and Objects in C + +\n"; }
Реализация данного класса включает в себя всего один метод, который печатает сообщение.
// classes.cpp: определяет точку входа для консольного приложения. #include "stdafx.h" #include <iostream> using namespace std; #include "message.h" int main(int argc, char* argv[]) { CppStudio objMessage; // объявление объекта objMessage.message(); // вызов функции класса message system("pause"); return 0; }
// код Code::Blocks
// код Dev-C++
// classes.cpp: определяет точку входа для консольного приложения. #include <iostream> using namespace std; #include "message.h" int main(int argc, char* argv[]) { CppStudio objMessage; // объявление объекта objMessage.message(); // вызов функции класса message return 0; }
Структура данной программы совсем простая, чего не скажешь о программах с большим объёмом кода. В таких программах, как правило, код расположен не в одном файле. И подключение заголовочных файлов выполняется не обязательно в главном файле. Поэтому существует вероятность многократного включения в программу заголовочного файла, что в свою очередь приводит к ошибке компиляции. В случае с нашей программой, заголовочный файл подключен в главном файле в строке 7 и программа нормально работает без всяких ошибок. А если же заголовочный файл message.h
, по ошибке, был подключён не только в главном файле программы, но, и ,например, в файле stdafx.h
. В таком случае при компиляции программы появится следующая ошибка:
//Ошибка 1 error C2011: CppStudio: переопределение типа "class"
То есть, компилятор сообщает о многократном включении заголовочного файла с классом CppStudio
. В таком случае придется потратить своё время и убрать лишнее включение в программу заголовочного файла. Чтобы не возникало такого рода ошибок, в С++ существует специальная структура кода, которую ещё называют препроцессорная обёртка.
// препроцессорная обёртка, файл: message.h с интерфейсом класса #ifndef CPPSTUDIO_H // если имя CPPSTUDIO_H ещё не определено #define CPPSTUDIO_H // определить имя CPPSTUDIO_H // определить класс CPPSTUDIO_H class CppStudio // имя класса { public: // спецификатор доступа void message(); // функция (метод класса) выводящая сообщение на экран }; // конец объявления класса CppStudio #endif CPPSTUDIO_H // если имя CPPSTUDIO_H уже определено, повторно не определять
Данная препроцессорная обёртка предотвращает попытку многократного включения заголовочных файлов. Препроцессорные директивы обрабатываются до этапа компиляции, программой-препроцессором. Который, в свою очередь не допускает многократного определения одного и того же класса. Препроцессорная обёртка похожа на оператор условного выбора if
. Директива #ifndef
проверяет, определено ли имя CPPSTUDIO_H
, если нет, то управление передаётся директиве #define
и определяется интерфейс класса. Если же имя CPPSTUDIO_H
уже определено, управление передаётся директиве #endif
. Таким образом, исключается возможность многократного определения класса CPPSTUDIO_H
.
Обратите внимание на то, как написано имя класса, используемое в сочетании с директивами препроцессорной обёртки — CPPSTUDIO_H
. Берётся имя заголовочного файла, в котором объявлен класс, причём имя принято записывать буквами верхнего регистра, а вместо точки ставить символ нижнего подчёркивания. Конечно же, имя может быть любым другим, но оно должно быть одинаковым во всех трёх директивах. Итак, структура препроцессорной обёртки такова:
// структура препроцессорной обёртки #ifndef /*ИМЯ ЗАГОЛОВОЧНОГО ФАЙЛА_H*/ #define /*ИМЯ ЗАГОЛОВОЧНОГО ФАЙЛА_H*/ // определение класса #endif /*ИМЯ ЗАГОЛОВОЧНОГО ФАЙЛА_H*/
С использованием препроцессорной обёртки, попытки подключения одного и того же файла, ошибки переопределения не вызовут. Этот же приём применяется и для предотвращения многократного определения функций, только если функции вынесены в отдельный файл.
Комментарии
Vaidokcrunk
Заказать Сиалис в РФ
Даже если взрослый мужик придерживается здорового образа жизни, ежегодно проходит все обследования и бегает по утрам, рано или поздно его все-равно поджидают трудности с потенцией: такова неприятная суть старения.
К большому счастью современная медицина создала [url=http://via-sexgra.ru/levitra-kupit-moskva]дженерик левитра отзывы[/url] , которые смогут продлить здоровую интимную жизнь на полтора десятка лет, не причиняя вреда при этом здоровью всех других органов и систем. Речь идет о Виагре дженериках, что вы можете заказать на этом портале via-sexgra.ru
Тут вас ожидает каталог из нескольких десятков препаратов, которые десятки лет производятся в США и прошли все нужные процедуры клинических проверок. В отличии от простых аптек, в указанном онлайн магазине все препараты продаются по минимальным расценкам и высылаются клиенту в простой посылке, что обеспечивает конфиденциальность заказа.
Все распространяемые таблетки изготавливаются на легальных европейских фармацевтических конвейерах и сопровождаются всеми легализованными документами. А небольшая стоимость дженериков обусловлена отсутствием огромной цепи посредников, как в случае с обычной аптекой.
Denya Lorents
Возможно эту статью следует переставить на чуть более ранний этап обучения? Где-то ближе к вынесению функции в отдельный файл.
Илья Бологан
а не проще с помощью
eagle_vik
Илья, можно и
, но учти что это работает только на Windows-платформах! Если ты будешь кодить под Unix системы, то там эту директиву не распознает, и она просто работать не будет!