Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЛР № 19 Программные модули в языках программиро...docx
Скачиваний:
2
Добавлен:
14.08.2019
Размер:
73.26 Кб
Скачать

Порядок выполнения работы

Ниже приведен листингпростой многофайловой программы, в которой определены типы данных «Точка» (структура Pointв файле Point.h) и «Прямоугольник» (структура Rectв файле Rect.h). Поскольку второй тип данных определяется через первый, вфайле Rect.hимеетсядиректива#include«Point.h». В основном модуле main.cppпросто создается объект типа «Прямоугольник» и выводятся координаты его левого верхнего и правого нижнего углов. В основном модуле используются как функции из модуля Point.срр. так и функции из модуля Rect.cpp. поэтому в него включены оба заголовочных файла Point.hи Rect.h. Но после обработки этих директив препроцессором окажется, что структура Pointопределена дважды. В результате компилятор выдаст сообщение об ошибке наподобие следующего: «error...; 'Point'; 'struct* typeredefinition».

///////// Файл Point.h//////////

// Объявления типов

structPoint

{

ititx;

inty;

};

// Прототипыфункций

voidSetXY(Point& point, int x. int y>;

intGetX(Point& point);

intGetY(Point& point);

////////// ФайлRect.h ////////////

♦include “Point.h”

// Объявлениятипов

structRect

{

Point leftTop;

Point rightBottom;

};

// Прототипыфункций

voidSetLTRB(Rect&rect, Point lt, Point rb);

voidGetLT(Rect&rect, Point&lt);

voidGetRB(Rect&rect, Point&rb);

////////// Файл Point.cpp ///////////

#include “Poin.h”

voidSetXY(Poin& point, int x, int y)

{

point.x=x;

poin.y=y;

}

intGetX(Point& point)

{

returnpoint.x;

}

intGetY(Point& point)

{

return point.у;

}

/////////// Файл Rect.cpp ///////////

#include “Rect.h”

voidSetLTRB(Rect&rect, Point lt. Point rb)

{

rect. leftTop = lt;

rect.rightBottom = rb;

}

voidGetLT(Rect& rect. Point&lt)

{

lt = rect.leftTop;

}

voidGetRB(Rect&rect, Point&rb)

{

rb = rect.rightBottom;

}

#include <stdio.h>

#include “Point.h”

#include “Rect.h”

/////////////// ФайлMain.cpp //////////////

int main()

{

Point ptl, pt2, lt. rb;

Rectrectl;

SetXV(ptl, 2, 5);

SetXY(pt2, 10, 14);

SetLTRB(rect1, ptl, pt2);

GetLT(rect1, lt);

GetRB(rect1, rb);

printf(“rect.lt.x = %d, rect.lt.y = %d\n, lt.x, lt.y);

printf(“rect.rb.x = %d, rect.rb.y = %d\n”, rb.x, rb.y);

return0;

}

Каков выход из этой ситуации? Бьерн Страуструп рекомендует использовать так называемые стражи включения, и этот способ нашел широкое применение. Он состоит в следующем: чтобы предотвратить повторное включение заголовочных файлов, содержимое каждого h-файла должно находиться между директивамиусловной компиляции #ifndefи #endif, как описано ниже:

#ifndef FILENAME_H

#define FILENAME_H

/* содержимое заголовочного файла */

#endif/* FILFNAME_H*/

Применительно к нашему примеру файл Point.hдолжеч содержать следующий текст:

//////////// ФайлPoint.h ///////////////

#ifndef P0INT_H

#define POINT_H

// Объявлениятипов

struct Point

{

int x;

inty;

};

//Прототипыфункций

voidSetXY(Point& point,int x, int y);

intGetX(Point& point);

intGetV(Point&point);

#endif/*P0INT_H*/