- •Концепция класса
- •Переменные класса
- •Методы класса
- •Наследование
- •Конструктор и деструктор
- •Виды памяти и создание объектов
- •Управление доступом к переменным и методам класса
- •Интерфейс
- •Исключения
- •Шаблоны
- •Введение в наследование
- •Множественное наследование классов
- •Преобразование типов
- •Виртуальные функции
Виды памяти и создание объектов
Во время работы программы переменные (в том числе объекты) могут создаваться в различных местах оперативной памяти: в сегменте данных, в стеке и в куче. Эти виды памяти отличаются принципом создания переменных в них.
В сегменте данных создаются переменные, существующие все время от начала работы программы до завершения. В эту категорию попадают все статические переменные (в том числе глобальные). С точки зрения программиста эти переменные всегда существуют и могут быть доступны.
Стек используется для передачи параметров в методы и для создания внутренних переменных методов, существующих только во время выполнения метода или его части. Создание переменных в сетке встраивается в объектный код программы компилятором и происходит прозрачно для программиста. Обращение программиста к переменным метода компилятор преобразует в обращение к стеку по фиксированному смещению от вершины (вглубь стека).
При вызове метода ее параметры помещаются на вершину стека. Если в методе объявлены другие переменные, то они также помещаются на вершину стека. В момент компиляции команды с обращением к той или иной переменной компилятор вычисляет по какому смещению располагается эта переменная относительно вершины стека и встраивает в объектный код программы ссылку на позицию в стеке по фиксированному смещению от вершины. При завершении работы метода или вложенного блока операторов, все переменные, объявленные в этом методе (или блоке), снимаются с вершины стека. Например, если в программе объявлены следующие функции:
void methodA (int x, float y) { int c; methodB (x, y, c); … -- Точка X } void methodB (int x, float y, int d) { int c; … -- Точка Y } |
то в точке Y в стеке будут существовать следующие переменные:
А в точке X следующие:
Использование кучи зависит от языка программирования. Например, в C++ создание переменных в куче полностью управляется программистом. После создания переменной программисту доступен указатель на ее начало. За удаление переменной в конце ее жизненного цикла отвечает сам программист, что служит причиной большого количества ошибок, приводящих к утечке памяти. В Java, наоборот, использование кучи прозрачно для программиста: если переменная представляет собой сложный объект, то она автоматически размещается в куче. Когда последняя ссылка на такой объект удаляется, он помечается неиспользуемым. В Java-машине существует регулярный процесс, называемый сборщиком мусора, который и отвечает за освобождение памяти из-под неиспользуемых объектов.
Если переменная представляет собой сложный объект, то во время ее создания вызывается конструктор, а во время уничтожения – деструктор, где бы она не находилась: в сегменте данных, в стеке или в куче.
Управление доступом к переменным и методам класса
Для переменных и методов класса может быть задан уровень доступа, регламентирующий доступ к переменным и методам одного класса из методов другого класса. Наиболее жестким является личный уровень доступа, дающий разрешение на доступ к переменным и методам только для методов самого класса. Наименее жестким – общий уровень доступа, дающий разрешение на доступ из любой точки программы. Средним вариантом является личный защищенный уровень доступа, когда доступ разрешен только для методов самого класса и его наследников. Уровень доступа в классе-потомке к переменной или методу класса-предка может быть изменен в сторону ужесточения. В зависимости от языка программирования промежуточные уровни доступа могут различаться. Так, например, в Java существует два дополнительных уровня доступа. В случае нарушения программистом регламента доступа к переменным во время компиляции программы будет выдано сообщение об ошибке. Приведем пример задания уровней доступа для переменных класса на языке C++:
class Person { private: -- Личный уровень доступа int number; -- Индивидуальный номер человека public: -- Общий уровень доступа char name[10]; -- Имя protected: -- Личный защищенный уровень доступа int age; -- Возраст float height; -- Рост }; |
В объектно-ориентированных языках программирования существуют механизмы описания исключений из перечисленных правил доступа. Первый механизм заключается в объявлении дружественности класса. Если некоторый класс A объявлен как дружественный некоторому классу B, то все методы A могут обращаться ко всем методами и переменным класса B, независимо от их уровня доступа. Например,
class B { … friend class A; -- Объявление дружественного класса. }; |
Второй механизм позволяет объявлять лишь некоторые методы класса A как дружественные классу B. Это приводит к возможности обращаться ко всем переменным и методам класса B, независимо от заданного для них уровня доступа, только в рамках этих методов. Например,
class B { … friend A::methodX; -- Объявление дружественного метода }; |