<<
>>

3.1. Определение класса

В C++, так же как и в других языках программирования, класс - это структурный тип, используемый для описания некоторого множества объектов предметной области, имеющих общие свойства и поведение.
Он описывается следующим образом:

class

{ private: внутренние (недоступные) компоненты класса>;

protected: ; public: ;

};

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

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

Компоненты класса, объявленные в секции protected, называются защищенными. Они доступны компонентным функциям не только данного класса, но и его потомков. При отсутствии наследования - интерпретируются как внутренние.

Компоненты класса, объявленные в секции public, называются общими. Они доступны за пределами класса в любом месте программы. Именно в этой секции осуществляется объявление полей и методов интерфейсной части класса.

Примечание. Если при описании секции класса тип доступа к компонентам не указан, то по умолчанию принимается тип private.

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

:: () {}

По правилам C++, если тело компонентной функции размещено в описании класса, то эта функция по умолчанию считается Встраиваемой (inline).

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

Так компонентные функции класса, описанного ниже, являются встраиваемыми по умолчанию:

#include

#,include

class X

{private: char c;

public: int x,y:

/* определение встраиваемых компонентных функций внутри

описания класса */

void print(void)

{ clrscrQ;

gotoxy(x,y); print/(" %c", c); x=x+10; y=y+5; gotoxy{x,y); print/(" %c", c);

}

void set_X(char ach,int ax,int ay) { c=ach; x=ax; y=ay; }

};

Встраиваемую компонентную функцию можно описать и вне определения класса, добавив к заголовку функции описатель inline.

При определении компонентных функций следует иметь в виду, что не

разрешается объявлять встраиваемыми:

- функции, содержащие циклы, ассемблерные вставки или переключатели;

- рекурсивные функции;

- виртуальные функции.

Тела таких функций обязательно размещаются вне определения класса. Например:

class Y

{ intx,y;

public: int k; char l;

H прототипы компонентных функций void print(void);

void set_ Y(char al,int ax,int ay,int ah');

};

// описание встраиваемой компонентной функции вне описания класса inline void Y::set_ Y(char al,int ax=40,int ay=15,int ak=15)

{ x=ax; y=ay; k=ak; l=al; }

/* описание компонентной функции print() содержит цикл, значит использовать режим inline нельзя */ void Y: .printО { clrscrQ; gotoxy(x,y);

for(int i=0;i String:: set_str{stl); ф]. String:: display_str().

Однако чаще доступ к компонентам объекта обеспечивается с помощью укороченного имени, в котором имя класса и двоеточие опускаются. В этом случае доступ к полям и методам осуществляется по аналогии с обращением к полям структур:

.;

-Химя поля или функции>;

[индекс]. .

Например:

a.str b->str c[i].str;

a.display_strQ b->display_str() c[i]. display_str Q.

Первая строка демонстрирует обращение к полям простого объекта, объекта, описанного как указатель на объект, и элемента массива объектов.

Вторая строка - обращение к методам соответствующих объектов.

Примечание. Обращение из программы возможно только к общедоступным компонентам класса. Доступ к внутренним и защищенным полям и функциям возможен только из компонентных и «дружественных» функций.

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

- глобальные и локальные статические объекты создаются до вызова функции main и уничтожаются по завершении программы;

- автоматические объекты создаются каждый раз при их объявлении и уничтожаются при выходе из функции, в которой они появились;

- объект, память под который выделяется динамически, создается функцией new и уничтожается функцией delete.

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

Значение может заноситься в поле объекта во время выполнения программы несколькими способами:

1) непосредственным присваиванием значения полю объекта;

2) внутри любой компонентной функции используемого класса;

3) согласно общим правилам C++ с использованием оператора инициализации.

Все вышеперечисленные способы применимы только для инициализации общедоступных полей, описанных в секции public.

Инициализация полей, описанных в секциях private и protected, возможна только с помощью компонентной функции.

Пример 3.2. Различные способы инициализации полей объекта

#,include

^include

#include class sstro { public:

char strl[40]; int x,y;

void set_str(char *vs) // функция инициализации полей

{ strcpy(strl,vs); х=0; у=0;}

voidprintiyoid) {coût«' '«х«' 'str this->fun().

Причем, при объявлении некоторого объекта А выполняется операция this=&A, а при объявлении указателя на объект b - операция this=b.

При работе с компонентами класса можно использовать этот указатель явным образом. Но следует отметить, что такое использование this не дает ощутимого преимущества, так как данные конкретных объектов уже доступны в принадлежащих классу функциях по именам.

Однако в некоторых случаях указатель this полезен и даже необходим. Очень удобным он становится, если в теле принадлежащей классу функции требуется явно задать адрес объекта, для которого она была вызвана.

Пример 3.3. Использование параметра this.

#include

#include class ТА { intx.y; public:

void set (int ax, int ay) {x=ax;y=ay;}

voidprint(void) { cout«x«' \t' next=this; last=this; }

void displayO { coût «str«endl; } static void disp layAQ; // объявление статической функции };

String *String::first=NULL; И инициализация статических компонент

String *String::last=NULL;

void String:: display All Q // описание статической функции { String *p=first; if {p—NULL) return;

Рис. 3.1. Организация списка объектов для примера 3.4

do {p->displayO; p=p->next;} while{p\=NULL)\

}

int main(void)

{ String а(“Это пример ”), И объявление - создание трех объектов класса b(“использования статических ”), с(“комронент

if (String: :first!=NULL) // обращение к общему статическому полю String:: display AIK)', И обращение к статической функции getchO;

}

Использование статических компонент класса позволяет снизить потребность в глобальных переменных, которые могли бы быть использованы с аналогичной целью.

Локальные и вложенные классы. Класс может быть объявлен внутри некоторой функции. Такой класс в C++ принято называть локальным. Функция, в которой объявлен локальный класс, не имеет непосредственного доступа к компонентам локального класса, доступ осуществляется с указанием имени объекта встроенного класса.

Локальный класс не может иметь статических полей. Объект локального класса может быть создан только внутри функции, в области действия объявления класса. Все компонентные функции локального класса должны быть встраиваемыми.

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

Пример 3.5. Вложенные классы. Пусть требуется разработать программу, которая рисует ломаную линию или многоугольник отрезками линий, заданных координатами точек начала и конца отрезков.

#include

#include

#include class Figura {

class Point II вложенный вспомогательный класс Точка { int x,y,cv; public:

int getxO (return x;} И метод получения координаты x int getyO (return у;} И метод получения координаты у int getcO (return cv;} И метод получения цвета void setpoint(int ncv) И метод задания координат точки и ее цвета

{coût«" введите координаты точки: " «endl; cin»x»y; cv=ncv;}

};

class Line II вложенный вспомогательный класс Линия

{ Point Tn, Tk; // начало и конец линии public:

void draw(void) 11 метод рисования линии

{ setcolor(Tn.getcQ);

Une(Tn.getxQ, Tn.getyO, Tk.getx(), Tk.getyO); }

void setline(int ncv) II метод задания координат точек линии

{coût«" введите координаты точек линии: " «endl;

Tn.setpoint(ncv); Tk.setpoint(ncv);} void printQ // метод вывода полей класса {cout«Tn.getx()«' ' «Tn.getyO«' cout«Tk.getxO«' ' «Tk.getyO«endl; }

};

// поля и методы класса Фигура ini holline; 11 количество отрезков Фигуры

Line *mas; И динамический массив объектов типа Линия

public:

void setßgura(int n,int ncv); II прототип метода инициализации объекта void draw(void); И прототип метода отрисовки линий

void delfiguraO {delete [] mas;} И метод уничтожения объекта void printQ; II прототип метода вывода координат точек

};

void Figura: :setfigura(int п, int ncv)

{ holline =n;

cout«" введите координаты" «holline«"линий:" «endl; mas=new Line [holline];

for (int i=0;i

<< | >>
Источник: Г.С.Иванова, Т.Н.Ничушкина, Е.К.Пугачев. Объектно- ориентированное программирование. 2001

Еще по теме 3.1. Определение класса:

  1. § 33 Общее правило о переходе наследства к детям. – Отличие отделенных от неотделенных. – Право представления. – Право родительское. – Право боковых родственников. – Римская система определения прав по классам и степеням. – Германская система определения прав по линиям и коленам.
  2. 40. Основные теоретические подходы в определении классов. Немарксистские подходы
  3. Школьный класс
  4. Одиночки в классе
  5. ПЕРВЫЙ КЛАСС
  6. ПЯТЫЙ КЛАСС
  7. 6.3. Женщина высшего класса
  8. 5. Критическая теория и рабочий класс.
  9. Глава 13. INTJ «Компетентность + независимость = высший класс»
  10. СРАВНИТЕЛЬНАЯ СИСТЕМА КЛАССОВ
  11. Масса, демократия и рабочий класс