Глава 10. Объектно-ориентированное программирование
return stream ;
}
i s t r e a m& operator>>(i s t r e a m& stream , s p a t i a l _ v e c t o r& b )
{
s t r e a m >> b . x >> b . y >> b . z ;
return stream ;
}
main ( )
{
s p a t i a l _ v e c t o r a , b ( 1 , 2 , 3 ) ;
c o u t << " \ n1. Заполнение вектора через стандартный ввод\ n " ;
c o u t << "Введите координаты вектора: " ;
c i n >> a ;
a . i n f o ( ) ;
c o u t << " \ n2. Вычитание векторов\ n " ;
s p a t i a l _ v e c t o r c = a−b ;
c o u t << "Координаты вектора с=a-b(1,2,3): " << c ;
c o u t << " \ n3. Изменение координаты вектора с помощью геттеров и сеттеров\ n " ;
c . set_x ( c . get_x ( ) +1) ;
c o u t << "После инкремента координаты x, координаты вектора c: " << c ;
c o u t << " \ n4. Инкремент:\ nвывод с++: " << c++;
c o u t << "Вывод ++с: " << ++c ;
}
Функция main() просит пользователя ввести с клавиатуры три координаты
вектора, а затем выполняет несколько тестов, демонстрирующих работу методов
класса. Например, при вводе значений «1 2 3» выводится следующий результат:
1. Заполнение вектора через стандартный ввод
Введите координаты вектора: 1 2 3
Координаты вектора: x=1; y=2; z=3
Модуль вектора равен 3.74166
2. Вычитание векторов
Координаты вектора с=a-b(1,2,3): x=0; y=0; z=0
3. Изменение координаты вектора с помощью геттеров и сеттеров
После инкремента координаты x, координаты вектора c: x=1; y=0; z=0
4. Инкремент:
вывод с++: x=1; y=0; z=0
Вывод ++с: x=3; y=2; z=2
Как можно заметить, в программе не перегружен оператор присваивания, а
в классе spatial_vector не задан конструктор копирования. В данном случае
класс не работает с динамической памятью и не нуждается в какой-то особой
предварительной инициализации и деинициализации, поэтому выполняемое по
умолчанию побитовое копирование объектов оказывается полностью приемле-
мым. Более того, передача параметра по значению активно используется в пе-
регруженных операторах сложения и вычитания, а также в постфиксной форме
инкремента и декремента. В первых двух случаях первый параметр (левый опе-
ранд) передаётся по значению, чтобы можно было изменить его и вернуть, не
затронув исходный объект. В перегруженных постфиксных операторах исполь-
зуется возврат исходной побитовой копии объекта, снятой до того, как ориги-
нальный объект был изменён.
Комбинирование в выражениях перегруженных операторов, некоторые из ко-
торых используют передачу по ссылке, а некоторые — по значению, требует тща-
Программирование на языке С++ в среде Qt Creator
10.4. Наследование
293
тельности в оформлении списка параметров. Если возвращённый по значению
результат работы одного оператора может быть принят другим по ссылке, во
избежание конфликтов соответствующий аргумент следует явно объявить кон-
стантным (см., например, второй параметр оператора потокового вывода). На
самом деле использование модификатора const в подобных случаях боле чем
логично, поскольку оператор не изменяет принятый аргумент, а передача по
ссылке используется исключительно для уменьшения накладных расходов на
копирование объекта.
10.4
Наследование
Наследование классов позволяет строить иерархию, наверху которой нахо-
дятся более общие классы, а внизу — более специализированные. Попробуем
привести наглядный пример иерархии наследования. Предположим, мы создаём
объектно-ориентированную систему работы с графикой, и предусмотрели класс
point
, описывающий отдельную двумерную точку на экране. В этом классе хра-
нятся координаты точки, её цвет, а также методы для управления этими дан-
ными. При необходимости можно легко создать на базе класса point производ-
ный класс, хранящий трехмерную вершину (например, vertex): добавить в нём
третью координату, соответствующие конструкторы, модифицировать некото-
рые методы. Однако не следует путать отношение наследования с отношением
включения. Например, будет нелогичным строить на базе класса point или клас-
са vertex класс region, описывающий объекты с произвольным количеством
вершин: скорее, это должен быть класс-контейнер, содержащий в себе массив
объектов point или vertex.
Таким образом, есть смысл создавать на базе существующего класса произ-
водный, если мы хотим получить частный случай с модифицированной функци-
ональностью.
В C++ новый класс строится на базе уже существующего с помощью конструк-
ции следующего вида:
c l a s s p a r e n t { . . . . . } ;
c l a s s c h i l d : [ модификатор наследования ] p a r e n t { . . . . . } ;
При определении класса-потомка, за его именем следует разделитель-
двоеточие «:», затем необязательный модификатор наследования и имя роди-
тельского класса. Модификатор наследования определяет видимость наследу-
емых переменных и методов для класса-потомка и его возможных потомков.
Таким способом определяется, какие права доступа к переменным и методам
класса-родителя будут «делегированы» классу-потомку.
При реализации наследования область видимости принадлежащих классу
данных и методов можно определять выбором одного из следующих модифи-
каторов доступа
:
• private (закрытый);
• public (общедоступный);
• protected (защищённый).
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В., Чмыхало А. С.
294
Do'stlaringiz bilan baham: |