Рейтинговые книги
Читем онлайн Освой самостоятельно С++ за 21 день. - Джесс Либерти

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 31 32 33 34 35 36 37 38 39 ... 170

18: int main()

19: {

20:    Cat Frisky(5);

21:    Frisky.Meow();

22:    cout << "Frisky is а cat who is ";

23:    cout << Frisky.QetAge()  << " years old.n";

24:    Frisky.Meow();

25:    Frisky.SetAge(7);

26:    cout << "Now Frisky is " ;

27:    cout  << Frisky.GetAge()  << " years old.n";

28:    return 0;

29: }

Результат:

Meow.

Frisky is а cat who is 5 years old.

Meow.

Now Frisky is 7 years old.

Анализ: Программа, представленная в листингах 6.6 и 6.7, аналогична программе из листинга 6.4 за исключением того, что три метода класса объявляются подставляемыми, а само объявление класса вынесено в файл заголовка CAT.hpp.

В строке 7 объявляется функция GetAge() и тут же следует определение ее выполнения. Строки 8 и 9 занимают объявления еще двух встроенных функций, но их определения содержатся в другом файле.

В строке 4 листинга 6.7 с помощью команды #include "cat.hpp" в программу включается содержимое файла CAT.hpp. Компилятор получает команду считать содержимое файла cat .hpp и ввести его в данный файл, начиная со строки 5.

Возможность встраивания файлов в другие файлы позволяет хранить объявления классов отдельно от их выполнения и использовать тогда, когда в этом возникает необходимость. Это стандартный прием при создании программ на языке C++. Обычно объявления классов хранятся в файле с расширением .hpp, который затем включается в соответствующий файл .cpp с помощью директивы #include.

В строках 18—29 в точности повторяется тело функции main() из листинга 6.4. Цель этого повторения — показать, что применение подставляемых вариантов функций не внесло изменений в использование этих функций.

Классы содержащие другие классы в качестве данных-членов

Нет ничего необычного в построении сложного класса путем объявления более простых классов и последующего включения их в объявление сложного класса. Например, можно объявить класс колеса, класс мотора, класс коробки передач и т.д., а затем объединить их в класс автомобиля. Тем самым объявляются и взаимоотношения между классами. Автомобиль имеет мотор, колеса и коробку передач.

Рассмотрим второй пример. Прямоугольник состоит из линий. Линия определяется двумя точками. Каждая точка определяется координатами x и у. В листинге 6.8 показано объявление класса Rectangle, которое содержится в файле RECTANGLE.hpp. Поскольку прямоугольник определяется четырьмя линиями, соединяющими четыре точки, и каждая точка имеет координаты на графике, то сначала будет объявлен класс Point для хранения координат x,y каждой точки. Листинг 6.9 содержит объявления обоих классов.

Листинг 6.8. Объявление классов точки и прямоугольника

1: // Начало файла Rect.hpp

2: #include <iostream.h>

3: class Point // хранит координаты x,y

4: {

5:    // нет конструктора, используется конструктор по умолчанию

6: public:

7:    void SetX(int x) { itsX = x; >

8:    void SetY(int у) { itsY = у; }

9:    int GetX() const < return itsX;}

10:   int GetY() const { return itsY;}

11: private:

12:   int itsX;

13:   int itsY;

14: }; // конец объявления класса Point

15:

16:

17: class Rectangle

18: {

19: public:

20:   Rectangle(int top, int left, int bottom, int right):.;

21:   ~Rectangle() {}

22:

23:   int GetTop() const { return itsTop; }

24:   int GetLeft() const { return itsLeft; }

25:   int GetBottom() const { return itsBottom; }

26:   int GetRight() const { return itsRight; }

27:

28:   Point GetUpperLeft() const { return itsUpperLeft; }

29:   Point GetLowerLeft() const { return itsLowerLeft; }

30:   Point GetUpperRight() const { return itsUpperRight; }

31:   Point GetLowerRight() const { return itsLowerRight; }

32:

33:   void SetUpperLeft(Point Location) {itsUpperLeft = Location; }

34:   void SetLowerLeft(Point Location) {itsLowerLeft = Location; }

35:   void SetUpperRight(Point Location) {itsUpperRight = Location; }

36:   void SetLowerRight(Point Location) {itsLowerRight = Location; }

37:

38:   void SetTop(int top) { itsTop = top; }

39:   void SetLeft (int left) { itsLeft = left; }

40:   void SetBottorn (int bottom) { itsBottom = bottom; }

41:   void SetRight (int right) { itsRight = right; }

42:

43:   int GetArea() const;

44:

45: private:

46:   Point itsUpperLeft;

47:   Point itsUpperRight;

48:   Point itsLowerLeft;

49:   Point itsLowerRight;

50:   int itsTop;

51:   int itsLeft;

52:   int itsBottom;

53:   int itsRight;

54: };

55: // конец файла Rect.hpp

Листинг 6.9. Содержимое файла RECT.cpp

1: // Начало файла rect.cpp

2: #include "rect.hpp"

3: Rectangle::Rectangle(int top, int left, int bottom, int right)

4: {

5:    itsTop = top;

6:    itsLeft = left;

7:    itsBottom = bottom;

8:    itsRight = right;

9:

10:   itsUpperLeft.SetX(left);

11:   itsUpperLeft.SetY(top);

12:

13:   itsUpperRight.SetXtright);

14:   itsUpperRight.SetY(top);

15:

16:   itsLowerLeft.SetX(left);

17:   itsLowerLeft.SetY(bottom);

18:

19:   itsLowerRight.SetX(right);

20:   itsLowerRight.SetY(bottom);

21: }

22:

23:

24: // Вычисляем площадь прямоугольника, отыскивая его стороны

25: // определяем его длину и ширину, а затем перемножаем их

26: int Rectangle::GetArea() const

27: {

28:   int Width = itsRignt - itsLeft;

29:   int Height = itsTop - itsBottom;

30:   return (Width >> Height);

31: }

32:

33: int main()

34: {

35:   //инициализируем локальную переменную Rectangle

36:   Rectangle MyRectangle (100, 20, 50, 80 );

37:

38:   int Area = MyRectangle.GetArea();

39:

40:   cout  << "Area: " << Area  << "n";

41:   cout  << "Upper Left X Coordinate:";

42:   cout  << MyRectangle.GetUpperLeft().GetX();

43:   return 0;

44: }

Результат:

Area: 3000

Upper Left X Coordinate: 20

Анализ: В строках 3-14 листинга 6.8 объявляется класс Point, который используется для хранения конкретных координат x,y на графике. В данной программе класс Point практически не используется. Однако в других методах рисования он незаменим.

Внутри объявления класса Point (в строках 12 и 13) объявляются две переменные- члена (itsX и itsY). Эти переменные хранят значения координат точки. При увеличении координаты x мы перемещаемся на графике вправо. При увеличении координаты у мы перемещаемся на графике вверх. В других графиках могут использоваться другие системы координат (с другой ориентацией). Например, в некоторых программах построения окон значение координаты у увеличивается при перемещении в области окна вниз.

В классе Point используются подставляемые inline-функции доступа, предназначенные для чтения и установки координат точек X и Y. Эти функции объявляются в строках 7-10. В объектах класса Point используются стандартные конструктор и деструктор, предоставляемые компилятором по умолчанию. Следовательно, координаты точек должны устанавливаться в программе.

В строке 17 начинается объявление класса Rectangle, который включает четыре точки, представляющие углы прямоугольника.

Конструктор класса Rectangle принимает четыре целочисленных параметра, именуемых top (верхний), left (левый), bottom (нижний) и right (правый). Эти четыре параметра, передаваемые конструктору, копируются в соответствующие четыре пере- менные-члена (см. листинг 6.9), после чего устанавливаются четыре точки (четыре объекта класса Point).

Помимо обычных функций доступа к данным-членам класса, в классе Rectangle предусмотрена функция GetArea(), объявленная в строке 43. Вместо хранения значения площади в виде переменной эта функция вычисляет площадь в строках 28 и 29 листинга 6.9. Для этого сначала вычисляются значения длины и ширины прямоугольника, а затем полученные результаты перемножаются.

Для получения координаты верхнего левого угла прямоугольника нужно получить доступ к точке UpperLeft и запросить ее значение X. Поскольку функция GetUpperLeft() является методом класса Rectangle, она может непосредственно получить доступ к закрытым данным этого класса, включая и доступ к переменной itsUpperLeft. Поскольку переменная itsUpperLeft является объектом класса Point, а переменная itsX этого объекта закрытая, функция GetUpperLeft() не может прямо обратиться к этой переменной. Вместо этого для получения значения переменной itsX она должна использовать открытую функцию доступа GetX().

В строке 33 листинга 6.9 начинается тело основной части программы. До выполнения строки 36 никакой памяти не выделялось и ничего, по сути, не происходило. Все, сделанное до сих пор, служило одной цели — сообщить компилятору, как создается точка и как создается прямоугольник (на случай, если в этом появится необходимость).

В строке 36 определяется прямоугольник (объект класса Rectangle) путем передачи реальных значений для параметров Top, Left, Bottom и Right.

В строке 37 создается локальная переменная Area типа int. Она предназначена для хранения площади созданного прямоугольника. Переменной Area присваивается значение, возвращаемое функцией-членом GetArea() класса Rectangle.

Клиент класса Rectangle может создать объект Rectangle и возвратить его площадь, не заботясь о нюансах выполнения функции GetArea().

В листинге 6.8 показано содержимое заголовочного файла Rect.hpp. Только лишь просмотрев заголовочный файл, который содержит объявление класса Rectangle, программист будет знать, что функция GetArea() возвращает значение типа int. Пользователя класса Rectangle не волнуют "производственные" секреты функции GetArea(). И в самом деле, автор класса Rectangle мог бы спокойно изменить выполнение функции GetArea(), и это бы не повлияло на программы, использующие класс Rectangle.

1 ... 31 32 33 34 35 36 37 38 39 ... 170
На этой странице вы можете бесплатно читать книгу Освой самостоятельно С++ за 21 день. - Джесс Либерти бесплатно.

Оставить комментарий