Объектно-ориентированное программирование



 

Цели:

ü получить представление о компонентах класса;

ü методику написания алгоритмов с использованием классов и перевода таких алгоритмов на язык программирования С++ и разработки соответствующего проекта в среде Visual C++ 6.0.

 

Компонентные данные и компонентные функции

При определении класса в его теле описываются и (или) определяются данные класса и принадлежащие ему функции.

Компонентные данные

 

Определение данных класса внешне аналогично обычному описанию объектов базовых и производных объектов типов. Класс в этом отношении полностью сохраняет все особенности структурированных типов. Именно поэтому данные класса могут быть названы его элементами. Элементы класса могут быть как базовых, так и производных типов, то есть компонентными данными служат переменные, массивы, указатели и т.д. Как обычно, описания элементов одного типа могут быть записаны в одном операторе. Например:

class point

{

float x, y, z; 

long a, b, c;

};

В отличие от обычного определения данных при описании элементов класса не допускается их инициализация. Это естественное свойство класса, так как при его определении ещё не существует участков памяти, соответствующих компонентным данным. Память выделяется не для класса, а только для объектов класса. Для инициализации компонентных объектов класса. Для инициализации компонентных данных объектов должен использоваться автоматический или явно вызываемый конструктор соответствующего класса. Существуют различия между обращениями к компонентным данным класса из принадлежащих ему функций и из других частей программы. Как уже показано на примерах, классы complex, stroka, принадлежащие классу функции, имеют полный доступ к его данным, то есть для обращения к элементу класса из тела компонентной функции достаточно использовать только имя элемента. Например, в одном конструкторе класса stroka используется оператор:

ch=new char [leh+1];

За простотой такого обращения к данным класса из его компонентной функции скрывается механизм неявного отождествления имён компонентных данных класса с элементами именно того объекта класса, для которого вызывается компонентная функция. Например, при таком определении объекта line класса stroka:

stroka line (20);

значения присваиваются именно переменным line.len и line.ch.

Для доступа к компонентным данным из операторов, выполняется вне определения класса, непосредственное использование имён элементов недопустимо. Смысл такого запрета определяется упомянутым механизмом привязки данного класса к конкретным объектам. В определение класса по существу не вводятся его данные, а только обозначается возможность их формирования при определении конкретных объектов класса. Явно размещается в памяти не класс, а конкретный объект класса. В отведённой для объектной области памяти выделяются участки, соответствующие компонентным данным (элементам объекта). Для обращения к элементу объекта нужно использовать операции выбора компонентов класса (‘.’ или ‘ –>’). Первая из них позволяет сформировать уточнённое имя по известному имени объекта:

<имя объекта> . <имя элемента>

Вторая операция обеспечивает обращение к компонентным данным объекта по заданному указателю на объект:

<указатель на объект> -> <имя объекта>

Хотя внешне компонентные данные класса могут быть подобны данным, определённым в блоке или в теле функции, но существуют некоторые различия. Данные класса не обязательно должны быть определены или описаны до их первого использования в принадлежащих классу функциях. То же самое справедливо и для принадлежащих классу функций, то есть обратиться из одной функции класса к другой можно до её определения внутри тела класса. Все компоненты класса «видны» во всех операторах его тела. Именно поэтому, кроме областей видимости «файл», «блок», «функция», в Си ++ введена особая область видимости «класс».

 

Определение компонентных функций

 

Компонентная функция должна быть обязательно описана в теле класса. В отличие от обычных (глобальных) функций компонентная функция имеет доступ ко всем компонентам класса (с любым статусом доступа). Функция–компонент класса имеет ту же область видимости, что и класс, к которому она относится. Программист может влиять на компилятор, предлагая ему оформить ту или иную функцию как представляемую (встраиваемую). Для этих целей в определении функции указывается служебное слово (спецификатор) inline. При определении классов их компонентные функции также могут быть специфицированы как подставляемые. Кроме явного использования служебного слова inline для этого используется следующее соглашение. Если определение (не только прототип) принадлежит классу функции полностью размещено в классе (в теле класса), то эта функция по умолчанию считается подставляемой. Именно таким образом определены компонентные функции классов complex1, complex, stroka, использованных ранее в качестве примеров. Все функции перечисленных классов воспринимаются компьютером как подставляемые, то есть при каждом вызове этих функций их код «встраивается» непосредственно в точку вызова.

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

При внешнем определении компонентной функции программист «должен сообщить» компилятору, к какому именно классу она относится. Для этого используется бинарная форма операции ‘::’ (указания области видимости).

Формат её использования в этом случае таков:

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

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

При внешнем определении компонентной функции в теле класса помещается её прототип:

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

Вне тела класса компонентная функция определяется таким образом:

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

{

<тело, принадлежащее классу функции>

}

В качестве примера программу с использованием класса «вектор в двумерном пространстве».

Компонентные данные (свойства) класса: координаты вектора.

Компонентные функции (методы) класса:

1) ввод координат;

2) вывод координат;

3) определение длины вектора.

// VECT.H

 class vect_2D

{

private:

      float x, y;

public:

      void get_x (float x1);

void get_y (float y1);

void print ();

float len ();

};

// Описание методов класса

void vect_2D : : get_x (float x1)

{ x=x1;} // Где x – компонент класса, x1 – передаваемое в get_x значение

void vect_2D : : get_y (float y1)

{ y=y1;}

void vect_2D : : print ()

{ printf (“{%f; %f}\n”, x, y); }

float vect_2D : : len ()

{

float z;

z=sqrt(x*x + y*Y);

return z;

}

Добавим этот объект класса в код программы, подключив проект «vect.h» в головном файле

#include “stdio.h”

#include “math.h”

#include “vect.h”

int main ( )

{

vect_2D v1, *v2;

float x, y, z;

v2=(vect_2D*) malloc (sizeof(vect_2D));

printf (“x=”); scanf (“%f”,&x);

printf (“y=”); scanf (“%f”,&y);

v1. get_x(x);

v1. get_y(y);

v2 – > get_x(x);

v2 – > get_y(y);

z=v1. print ( );

free (v2);

return 1;

}

Лекция 2 5


Дата добавления: 2019-11-25; просмотров: 174; Мы поможем в написании вашей работы!

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






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