5. Компонентные данные классов. 6. Компонентные функции классов.

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

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

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

имя_класса::имя_статической_функции

Две специфические операции языка С++ : ".*" и "->*" предназначены для работы с указателями на компоненты класса.  Указатель на компоненты класса не может адресовать никакого участка памяти. Указатели на компоненты класса по-разному определяются для данных и функций класса. Указатель на компонентную функцию имеет вид:

тип_возв-ых_функцией_значений(имя_класса::*имя_указателя_на_метод)

(спецификация_параметров_функции);   

Для компонентнной  функций double& re( ); указатель определяется так: double& (complex1 : : * ptCom ) ( );.

Описав указатель ptCom можно задать его значения ptCom = &complex1 : : re;. Теперь для любого объекта А  класса complex1:

complex1 A(10.0, 2.4); можно вызвать принадлежащую классу функцию (A.*ptCom)()=11.1; cout<<(A.*ptCom)();

Формат определения указателя на компонентные данные класса:

тип_данных (имя_класса : : *имя_указателя );

В определение указателя можно включить явную инициализацию:

&имя_класса : : имя_компонента;

При этом компонент класса должен быть общедоступным (public).

complex1 comp;

comp.real=16.0;

comp.imag=33.4;

double (complex1::*pdat )=&complex1::imag;

cout<<“\ n comp.imag=“<<comp.*pdat;

pdat=&complex1::real;

cout<<“\ n comp.real=“<<comp.*pdat;

‘.*‘ - операция разименования указателей на компоненты класса имеет следующий синтаксис:

имя_объекта.*указатель_на_компонентные_данные

или

имя_объекта.*указатель_на_метод (параметры )

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

указатель_на_объект_класса ->*указатель_на_компонент_данных

или

указатель_на_объект_класса ->*указатель_на_ метод(параметры)

 

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

имя_класса : : имя_компонентной_функции

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

тип  имя_функции (спецификация_и_инициализация_параметров);

Вне тела класса определение функции выглядит так:

тип имя_класса::

имя_функции(спецификация_формальных_параметров)

{ тело функции }

// Point.h

#ifndef  POINTH

#define  POINTH  1

class  point

{              protected:

int  x, y;

public:

point (int xi=0, int  yi=0 );  // Конструктор

int& givex (void);

int&  givey (void);

void  show (void);

void  move (int xn=0, int yn=0);

prevate:

void hide ();      // Убрать с экрана изображение точки

};

#endif

Описание класса point может появляться в компилируемом файле только однократно, так как условная препроцессорная директива  #ifndef POINTH защищает его от дублирования. В прототипе конструктора и функции move()  имена формальных параметров можно было опустить.

#ifndef   POINTCPP

#define POINTCPP  1

#include <graphics.h>

#include “point.h”

point::point (int xi, int yi)                            { x=xi; y=yi; }

int& point : : givex (void)                             { return x; }

int& point : : givey (void)                             { return y; }

void point : : show (void)                            { putpixel (x, y, getcolor()); }

void point : : hide (void)                              { putpixel (x, y, getbkcolor()); }

void point : : move (int xn, int yn)           { hide();  x=xn; y=yn;show(); }

#endif

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

void main ()

{              point  A(200,50);              //создается невидимая точка А

point  B;                              //создается невидимая точка B с нулевыми координатами

point D (500,200);

int dr=DETECT, mod      

initgraph (&dr, &mod, “c:\\ BCH\\ bgi “);                            //инициализация графики

A.show(); getch();  B.show(); getch(); D.show(); getch(); A.move(50,60); getch();

closegraph(); 

}

Hosted by uCoz