Использование оператора sizeof для гарантии переносимости программного кода



 

Как было показано, структуры и объединения создают объекты различных размеров, которые зависят от размеров и количества их членов. Более того, размеры таких встроенных типов, как int , могут изменяться при переходе от одного компьютера к другому. Иногда компилятор заполняет структуру или объединение так, чтобы выровнять их по границе четного слова или абзаца. (Абзац содержит 16 байт.) Поэтому, если в программе нужно определить размер (в байтах) структуры или объединения, используйте оператор sizeof . Не пытайтесь вручную выполнять сложение отдельных членов. Из‑за заполнения или иных аппаратно‑зависимых факторов размер структуры или объединения может оказаться больше суммы размеров отдельных их членов.

И еще. Объединение всегда будет занимать область памяти, достаточную для хранения его самого большого члена. Рассмотрим пример.

 

 

Здесь при выполнении оператора sizeof u_var получим результат 8 (при условии, что double ‑значение занимает 8 байт ). Во время выполнения программы не имеет значения, что реально будет храниться в переменной u_var; здесь важен размер самой большой переменной, входящей в состав объединения, поскольку объединение должно иметь размер самого большого его элемента.

 

Переходим к объектно‑ориентированному программированию

 

Эта глава заключает описание не объектно‑ориентированных атрибутов C++. Начиная со следующей главы, мы будем рассматривать средства, которые поддерживают объектно‑ориентированное программирование (Object Oriented Programming– OOP), или ООП . Чтобы понять объектно‑ориентированные средства C++ и научиться их эффективно применять, необходимо глубокое понимание материала этой и предыдущих девяти глав. Поэтому, возможно, вам стоит повторить пройденный материал. Особое внимание при повторении уделите указателям, структурам, функциям и перегрузке функций.

 

Глава 11: Введение в классы

 

В этой главе мы познакомимся с классом. Класс – это фундамент, на котором построена С++‑поддержка объектно‑ориентированного программирования, а также ядро многих более сложных программных средств. Класс – это базовая единица инкапсуляции, которая обеспечивает механизм создания объектов.

 

Основы понятия класса

 

Объектно‑ориентированное программирование построено на понятии класса.

Начнем с определения терминов класса и объекта. Класс определяет новый тип данных, который задает формат объекта . Класс включает как данные, так и код, предназначенный для выполнения над этими данными. Следовательно, класс связывает данные с кодом . В C++ спецификация класса используется для построения объектов. Объекты – это экземпляры класса. По сути, класс представляет собой набор планов, которые определяют, как строить объект. Важно понимать, что класс – это логическая абстракция, которая реально не существует до тех пор, пока не будет создан объект этого класса, т.е. то, что станет физическим представлением этого класса в памяти компьютера.

Определяя класс , вы объявляете данные, которые он содержит, и код, который выполняется над этими данными. Хотя очень простые классы могут содержать только код или только данные, большинство реальных классов содержат оба компонента. В классе данные объявляются в виде переменных, а код оформляется в виде функций. Функции и переменные, составляющие класс, называются его членами . Таким образом, переменная, объявленная в классе, называется членом данных , а функция, объявленная в классе, называется функцией‑членом . Иногда вместо термина член данных используется термин переменная экземпляра (или переменная реализации ).

Объявление класса начинается с ключевого слова class.

Класс создается с помощью ключевого слова class . Объявление класса синтаксически подобно объявлению структуры. Рассмотрим пример. Следующий класс определяет тип queue , который предназначен для реализации очереди. (Под очередью понимается список с дисциплиной обслуживания в порядке поступления, т.е. "первым прибыл – первым обслужен".)

 

 

Рассмотрим подробно объявление этого класса.

По умолчанию члены класса являются закрытыми (private‑членами).

Все члены класса queue объявлены в теле инструкции class . Членами данных класса queue являются переменные q , sloc и rloc . Кроме того, здесь определено три функции‑члена: init() , qput() и qget() .

Любой класс может содержать как закрытые, так и открытые члены. По умолчанию все элементы, определенные в классе, являются закрытыми. Например, переменные q , sloc и rloc являются закрытыми. Это означает, что к ним могут получить доступ только другие члены класса queue; никакие другие части программы этого сделать не могут. В этом состоит одно из проявлений инкапсуляции: программист в полной мере может управлять доступом к определенным элементам данных. Закрытыми можно объявить и функции (в этом примере таких нет), и тогда их смогут вызывать только другие члены этого класса.

Ключевое слово public используется для объявления открытых членов класса.

Чтобы сделать части класса открытыми (т.е. доступными для других частей программы), необходимо объявить их после ключевого слова public . Все переменные или функции, определенные после спецификатора public , доступны для всех других функций программы. Итак, в классе queue функции init() , qput() и qget() являются открытыми. Обычно в программе организуется доступ к закрытым членам класса через его открытые функции. Обратите внимание на то, что после ключевого слова public стоит двоеточие.

Следует иметь в виду, что объект образует своего рода связку между кодом и данными. Так, любая функция‑член имеет доступ к закрытым элементам класса. Это означает, что функции init() , qput() и qget() имеют доступ к переменным q , sloc и rloc . Чтобы добавить функцию‑член в класс, определите ее прототип в объявлении этого класса.

Определив класс, можно создать объект этого "классового" типа, используя имя класса. Таким образом, имя класса становится спецификатором нового типа. Например, при выполнении следующей инструкции создается два объекта Q1 и Q2 типа queue ,

 

 

После создания объект класса будет иметь собственную копию членов данных, которые составляют класс. Это означает, что каждый из объектов Q1 и Q2 будет иметь собственные отдельные копии переменных q , sloc и rloc . Следовательно, данные, связанные с объектом Q1 , отделены (изолированы) от данных, связанных с объектом Q2 .

Чтобы получить доступ к открытому члену класса через объект этого класса, используйте оператор "точка" (именно так это делается и при работе со структурами). Например, чтобы вывести на экран значение переменной sloc , принадлежащей объекту Q1 , используйте следующую инструкцию.

 

 

Давайте вспомним: в C++ класс создает новый тип данных, который можно использовать для создания объектов. В частности, класс создает логическую конструкцию, которая определяет отношения между ее членами. Объявляя переменную класса, мы создаем объект. Объект характеризуется физическим существованием и является конкретным экземпляром класса. (Другими словами, объект занимает определенную область памяти, а определение типа – нет.) Более того, каждый объект класса имеет собственную копию данных, определенных в этом классе.

В объявлении класса queue содержатся прототипы функций‑членов. Поскольку функции‑члены обеспечены своими прототипами в определении класса, их не нужно помещать больше ни в какое другое место программы.

Чтобы реализовать функцию, которая является членом класса, необходимо сообщить компилятору, какому классу она принадлежит, квалифицировав имя этой функции с именем класса. Например, вот как можно записать код функции qput() .

 

 

Оператор разрешения области видимости квалифицирует имя члена вместе с именем его класса.

Оператор "::" называется оператором разрешения области видимост и. По сути, он сообщает компилятору, что данная версия функции qput() принадлежит классу queue . Другими словами, оператор "::" заявляет о том, что функция qput() находится в области видимости класса queue . Различные классы могут использовать одинаковые имена функций. Компилятор же определит, к какому классу принадлежит функция, с помощью оператора разрешения области видимости и имени класса.

Функции‑члены можно вызывать только относительно заданного объекта. Чтобы вызвать функцию‑член из части программы, которая находится вне класса, необходимо использовать имя объекта и оператор "точка" . Например, при выполнении этого кода будет вызвана функция init() для объекта ob1 .

 

 

При вызове функции ob1.init() действия, определенные в функции init() , будут направлены на копии данных, относящиеся к объекту ob1 . Следует иметь в виду, что ob1 и ob2 – это два отдельных объекта. Это означает, что, например, инициализация объекта ob1 отнюдь не приводит к инициализации объекта ob2 . Единственное, что связывает объекты ob1 и ob2 , состоит в том, что они имеют один и тот же тип.

Если одна функция‑член вызывает другую функцию‑член того же класса, не нужно указывать имя объекта и использовать оператор "точка" . В этом случае компилятор уже точно знает, какой объект подвергается обработке. Имя объекта и оператор "точка" необходимы только тогда, когда функция‑член вызывается кодом, расположенным вне класса. По тем же причинам функция‑член может непосредственно обращаться к любому члену данных своего класса, но код, расположенный вне класса, должен обращаться к переменной класса, используя имя объекта и оператор "точка" .

В приведенной ниже программе класс queue иллюстрируется полностью (для этого объединены все уже знакомые вам части кода и добавлены недостающие детали).

 

 

При выполнении эта программа генерирует такие результаты.

 

 

Не забывайте, что закрытые члены класса доступны только функциям, которые являются членами этого класса. Например, такую инструкцию

 

 

нельзя включить в функцию main() нашей программы.

 


Дата добавления: 2018-09-22; просмотров: 342; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!