Стражи включения
Часть раздела Объектно-ориентированное программирование путешествия по C на Coddy. Урок 2 из 61.
Когда заголовочный файл включается в проект несколько раз, компилятор многократно видит одни и те же объявления, что приводит к ошибкам. Обычно это происходит, когда несколько файлов включают один и тот же заголовочный файл или когда заголовочные файлы включают друг друга. Защитные макросы решают эту проблему.
Защитный макрос использует три директивы препроцессора, чтобы содержимое заголовочного файла обрабатывалось только один раз:
// math_utils.h
#ifndef MATH_UTILS_H
#define MATH_UTILS_H
int add(int a, int b);
#endif
Вот как это работает: #ifndef MATH_UTILS_H проверяет, был ли символ MATH_UTILS_H ещё не определён. Если он ещё не был определён, препроцессор продолжает работу и сразу определяет его с помощью #define MATH_UTILS_H. Всё, что находится между этим местом и #endif, включается в компиляцию.
При втором включении этого заголовочного файла MATH_UTILS_H уже определён, поэтому весь блок пропускается. Имя защитного макроса обычно представляет собой имя файла в верхнем регистре, где точки и специальные символы заменены на подчёркивания.
В каждом заголовочном файле, который ты создаёшь, должны быть защитные макросы. Это стандартная практика, которая предотвращает ошибки компиляции и позволяет безопасно подключать файл из любой части проекта.
Задание
ЛегкоЗащитим заголовочный файл от повторного включения с помощью защитных макросов. Ты продолжишь работу с утилитой приветствия из предыдущего урока, но на этот раз сделаешь заголовочный файл безопасным для многократного включения.
Ты создашь два файла:
greet.h: заголовочный файл, содержащий объявление функцииgreet. На этот раз заключи всё содержимое в защитные макросы, используя символGREET_H.main.c: основной файл, который подключает заголовочный файл, реализует функциюgreetи вызывает её изmain().
Функция greet должна принимать параметр типа const char* для имени и выводить:
Hello, Alice!Твой заголовочный файл должен иметь следующую структуру:
#ifndef GREET_H
#define GREET_H
// function declaration here
#endifНа вход будет подано одно значение: имя (строка).
Выведи приветствие точно в указанном выше формате, заменив Alice на полученное имя.
Попробуйте сами
#include <stdio.h>
#include "greet.h"
// TODO: Реализуйте функцию greet, которая выводит "Hello, <name>!"
int main() {
char name[100];
scanf("%s", name);
// TODO: Вызовите функцию greet, передав ей имя
return 0;
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы модульного программирования
Заголовочные файлыСтражи включенияИсходные файлыСтатические функцииПовторение: Модульный калькулятор4Инкапсуляция
Концепция непрозрачных указателейОпределение непрозрачных структурГеттеры и сеттерыВалидация в сеттерахИтоги: Секретный ящик2Объекты и методы
Структуры как объектыУказатель 'Self'Константная корректностьУказатель против значенияВспомогательные методыИтоги: Point Manager5Проект: Простой банковский счет
Настройка проектаРеализация счета3Жизненный цикл объекта
Паттерн «Конструктор»Паттерн «Деструктор»Инициализация в стекеГлубокое копированиеПовторение: String Wrapper6Наследование через композицию
Встраивание структурПравило первого элементаДоступ к элементам родителяUpcastingПовторение: Иерархия фигур9Проект: Рисование фигур
Обзор проектаРеализация кругаРеализация прямоугольникаПолиморфное использованиеКонтейнер фигурПотренируйтесь самостоятельно: Онлайн-компилятор C