Читайте также: |
|
Классы
Понятие класса доставляет метод организации данных и функций в рамках одной и той же структуры. Классы объявляются с помощью ключевого class , и их функционирование подобно структурам в языке C, но при этом в качестве компонентов допускается включение функций, а не только данных
Синтаксическая форма для класса:
class class_name { permission_label_1: member1; permission_label_2: member2 ;... } object_name;где class _ name есть имя класса (определяемый пользователем тип) и, по выбору, одно или более имен object _ name , являющихся правильными идентификаторами объектов. Тело объявления может содержать члены (или компоненты, members ), которые могут быть либо данными, либо объявлениями функций, и, по выбору, метки вида доступа или, по-другому, спецификаторы доступа ( permission labels ) , которые могут быть любыми из трех ключевых слов: private : , public : или protected : . Они разбивают тело класса на секции, так, что входящие в них члены доступны при выполнении соответствующих прав доступа:
Если мы объявляем член класса до (перед) любой метки доступа (спецификатора прав доступа), то такой член считается закрытым ( private ) , поскольку доступ к членам класса по умолчанию – private .
Например :
class CRectangle { int x, y; public: void set_values (int,int); int area (void); } rect;Объявляется класс CRectangle и объект этого класса (типа), названный rect . Этот класс содержит четыре члена: две переменные типа int ( x и y ) в private - секции (по умолчанию) и две функции в public - секции: set _ values () и area () , где включены только их прототипы.
Обратим внимание на различие в использовании имени класса и имени объекта: CRectangle – имя класса(то есть user-defined тип), а rect – объект типа CRectangle . Это такое же различие, как и при объявлении переменной:
int a ;
int – это имя класса (тип) и a – имя объекта (переменной). После определения класса мы могли бы просто написать: CRectangle rect1, rect2; Таким образом, поскольку класс обладает всеми правами типа, можно определять и описывать объекты класса и создавать производные типы:
CRectangle rA, rB;
CRectangle *prA=&rA; //указатель
CRectangle array[5]; //массив
CRectangle &refB=rB; //ссылка
В последующих инструкциях в теле программы мы можем ссылаться на любой из открытых членов объекта rect , как на обычные функции или переменные, только используя при этом имя объекта и операцию выбора (“точка” или ->, если через указатель) (как в C-структурах). Например:
rect.set_value (3,4);
myarea = rect.area();
но мы не можем так поступить с закрытыми членами x или y , так как к ним разрешен доступ только из других членов того же класса (или друзей). Вот пример:
// classes example #include <iostream.h> class CRectangle { int x, y; public: void set_values (int,int); int area (void) {return (x*y);}}; void CRectangle::set_values (int a, int b) { x = a; y = b;} int main () { CRectangle rect; rect.set_values (3,4); cout << "area: " << rect.area();}
area : 12
Обратим внимание на использование операции разрешения области действия, ::, приопределении set _ values () . Она необходима, если член класса определяется вне класса. С помощью :: специфицируется тот класс, которому принадлежит определяемый член. Простые ф-ии, методы класса, часто определяют внутри класса и тогда, по умолчанию, они считаются встроенными функциями (inline).
Для простых классов, как у нас, размещение данных x и y в private -секции может показаться несколько надуманным, но для больших проектов важно иметь способ защиты данных он неожиданного и несанкционированного изменения.
// class example #include <iostream.h> class CRectangle { int x, y; public: void set_values (int,int); int area (void) {return (x*y);}}; void CRectangle::set_values (int a, int b) { x = a; y = b;}int main () { CRectangle rect, rectb; rect.set_values (3,4); rectb.set_values (5,6); cout << "rect area: " << rect.area() << endl; cout << "rectb area: " << rectb.area() << endl;}
rect area: 12
rectb area: 30
Вызов rect . area () не дает, естественно, тот же результат, что и rectb . area () . Каждый объект класса CRectangle имеет свои собственные переменные x и y , и собственные ф-ии set _ value () and area () .
На понятии объекта основана методология ООП. Данные определяют свойства объекта, а функции-методы – поведение. О методах класса, которые обеспечивают доступ к полям класса, часто говорят как об интерфейсе класса. Об объекте, созданном и функционирующем в памяти компьютера, говорят как об экземпляре класса.
Конструкторы и деструкторы
Объекты, в общем случае, нуждаются в инициализации переменных или выделении динамической памяти при их создании, для того чтобы быть полностью функциональными (дееспособными) и чтобы избежать появления непредсказуемых значений полей во время выполнения программы. Например, что произойдет, если мы вызовем, в нашем примере, функцию area () до вызова ф-ии set _ values ?
Чтобы не получать неопределенных результатов в подобных ситуациях, в класс включается специальная функция, называемая конструктором, которая имеет то же имя, что и класс. Конструктор будет автоматически вызван всякий раз, когда необходимо создать новый экземпляр класса (когда объявляется новый объект или выделяется память под новый объект класса). Формат определения конструктора в теле класса может быть таким: имя_класса (список_форм._параметров) {операторы_тела_конструктора}. В общем случае конструктор может быть как угодно сложным.
Вот как будет выглядеть программа для нашего класса CRectangle:
// classes example #include <iostream.h> class CRectangle { int width, height; public: CRectangle (int,int); int area (void) {return (width*height);}}; CRectangle::CRectangle (int a, int b) { width = a; height = b;}int main () { CRectangle rect (3,4); CRectangle rectb (5,6); cout << "rect area: " << rect.area() << endl; cout << "rectb area: " << rectb.area() << endl;}Обратим внимание на способ, которым параметры-аргументы передаются конструктору в момент создания экземпляра класса:
CRectangle rect (3,4);
CRectangle rectb (5,6);
Конструктор не имеет возвращаемого значения (даже тип void не указывается).
Функция деструктор выполняет обратную по отношению к конструктору задачу. Он автоматически вызывается, когда необходимо освободить память занимаемую объектом или при выходе из области действия объекта (например, если объект определен как локальный в некоторой функции и функция завершается и объект перестает существовать), или потому, что объект был создан динамически с помощью операции new и уничтожается операцией delete .
Деструктор должен иметь имя, как и имя класса, но с префиксом тильда ( ~ ). Деструктор также не имеет возвращаемого значения. У деструктора не может быть передаваемых параметров, даже типа void. Вот пример с деструктором:
// example on constructors and destructors #include <iostream.h> class CRectangle { int *width, *height; public: CRectangle (int,int); // CRectangle (int a=1,int b=1); ~CRectangle (); int area (void) {return (*width * *height);}}; CRectangle::CRectangle (int a, int b) { width = new int; height = new int; *width = a; *height = b;} CRectangle::~CRectangle () { delete width; delete height;}int main () { CRectangle rect (3,4), rectb (5,6); cout << "rect area: " << rect.area() << endl; cout << "rectb area: " << rectb.area() << endl; return 0;}Еще несколько слов о конструкторах. Существуют особенности в вызове конструктора. Без явного указания программиста конструктор всегда вызывается автоматически при определении (создании) объекта класса. При этом используются значения параметров по умолчанию. Конструктор превращает фрагмент памяти в объект того типа, который предусмотрен определением класса. В С++ конструктор существует для любого класса, причем он может быть создан без указания программиста. В классе может быть несколько конструкторов (перегрузка), но только один с умалчиваемыми значениями параметров. Нельзя получить адрес конструктора. Параметром конструктора не может быть его собственный класс, но может быть ссылка на него (см. конструктор копирования). Конструктор нельзя вызывать как обычную компонентную функцию. Для явного вызова конструктора можно использовать две разные синтаксические формы:
Имя_класса имя_объекта(аргументы_конструктора);
Имя_класса(аргументы_конструктора);
Первая форма допускается только при непустом списке фактических параметров. Она предусматриваеи вызов конструктора при определении нового объекта данного класса: CRectangle Myrect(3,4);
Вторая форма явного вызова конструктора приводит к созданию объекта, не имеющего имени. Создаваемый таким вызовом безымянный объект может использоваться в тех выражениях, где допустимо применение объекта данного класса. Например,
CRectangle Myrect=CRectangle(2,2); //создается объект Myrect со значением безымянного
Дата добавления: 2015-11-16; просмотров: 49 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Директива #undef . | | | Перегруженные конструкторы |