Лекция №

Вид материалаЛекция
1.3Вопросы по теме
2Методы объектно-ориентированного программирования. Лекция №6. 2.1Инкапсуляция
Конструкторы и деструкторы. Лекция №7.
Друзья класса
Подобный материал:
1   2   3   4   5   6   7   8   9   10   11

1.3Вопросы по теме

  1. Дать определение инкапсуляции.
  2. Дать определение наследования.
  3. Дать определение полиморфизма.
  4. Дать сравнительную характеристику процедурного и объектно-ориентированного программирования.
  5. Перечислить основные этапы разработки программ.

2Методы объектно-ориентированного программирования. Лекция №6.

2.1Инкапсуляция


Инкапсуляция (encapsulation) - это объединение данных и функций для работы с этими данными в классы. Метод инкапсуляции реализуется механизмом классов.

Класс


Класс - это совокупность элементов-данных различных типов и элементов-функций для их обработки с атрибутами доступа к ним.

Синтаксис определения класса:

class cl //cl - имя класса (идентификатор типа)

{

atr: //atr - атрибут доступа (private,public,protected)

tip1 per1; //элементы-данные

[...]

tf1 f1(tp1 p1[,...]);//прототипы элементов-функций

[...] //...новые атрибуты и новые элементы

[...] //конструкторы и деструкторы

[...] //друзья класса

};

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

Синтаксис объявления объекта класса: cl obj;

Атрибуты (спецификаторы доступа) осуществляют управление доступом к элементам класса:

private - закрытые элементы, доступны только для элементов-функций данного класса и друзей класса;

public - открытые элементы, доступны для любых функций;

protected - защищенные элементы, доступны для элементов-функций данного класса и производных классов.

По умолчанию действует private.

Структуры и объединения рассматриваются как типы классов с атрибутом доступа public.

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

Пример:

//файл заголовков //файл кодов

class akt void akt::vvod()

{ {

void vvod(); ...

}; }

Элементами класса служат элементы-данные и элементы-функции.

Элементы-данные - это совокупность взаимосвязанных данных различных типов, объявленная в определении класса.

Элементы-данные характеризуются следующими свойствами:
  • могут быть базового типа, массивами, типами, определяемыми пользователем, объектами ранее объявленного класса;
  • не могут быть объектами данного класса, но могут быть указателями или ссылками на объекты данного класса;
  • не могут быть явно инициализированы в теле класса (можно с помощью конструктора, см. ниже);
  • не могут иметь спецификаторы auto, extern, register;
  • могут иметь статический класс памяти (static); такие элементы-данные совместно используются всеми объектами данного класса (существует только по одному экземпляру таких данных); они должны быть объявлены в определении класса в файле заголовков и определены в файле кодов, где могут быть инициализированы (нельзя инициализировать в теле класса и элементах-функциях);
  • могут быть именными константами (const); должны быть инициализированы (например, с помощью конструктора).

Пример:

//файл заголовков //файл кодов

class listok long listok::nadbavka;

{... ...

static long nadbavka;

const char* otdel;

};

Элементы-функции - это функции, объявленные в определении класса и обрабатывающие элементы-данные класса.

Элементы-функции характеризуются следующими свойствами:
  • могут быть определены внутри или вне определения класса;
  • имеют доступ ко всем элементам данного класса независимо от их расположения в теле класса;
  • каждая не статическая элемент-функция при ее вызове объектом получает неявно объявленную переменную this (зарезервированное слово), которая является указателем на объект класса;
  • могут иметь статический класс памяти (static); такие функции могут обращаться только к статическим элементам класса и не могут быть объявлены const и virtual; они не связаны с объектами класса, т.е. при вызове не получают указатель this;
  • могут быть константными (const ставится за списком параметров функции); такие функции не могут изменять значения элементов-данных класса, что ведет к более устойчивому тексту программы.

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

Элементы класса имеют область действия этого класса. Доступ к элементам класса может выполняться следующими способами:
  • прямой доступ (по имени элемента) - из элементов-функций этого класса или из производных классов;
  • через объект класса - из внешних функций или из других классов, например, во внешней функции имеем obj.sozdanie(); , где obj - объект класса ved и sozdanie() - элемент-функция класса ved;
  • через указатель на объект класса, например, pobj->vvod(), где pobj - указатель на объект obj класса akt (akt* pobj=&obj);
  • через имя класса с операцией разрешения видимости (::), например, akt::chtenie_zap() или cena::chtenie_zap() при доступе из производного класса ved .

Схема доступа к элементам класса cl1 (без наследования):

class cl1 //внешняя функция или

{ //функция другого класса

private: cl1 obj; //или cl1* p=&obj;

int a; //доступ только к c и z()

void x(); //например,

protected: obj.z(); //или p->z();

int b; obj.c=10;//или p->c=10;

void y();

public:

int c;

void z();

}; //любая функция класса cl1 имеет доступ к a, x(), b, y(), c, z()

Остановимся на понятии указателя this. Каждая не статическая элемент-функция класса имеет доступ к объекту, для которого она вызвана, с помощью переменной this (неявного указателя). При вызове элемента-функции указатель this инициализируется адресом конкретного объекта класса. Например, при вызове obj.z() в стек загружается значение &obj, а в теле функции оператор a=10 интерпретируется как (&obj)->a=10. Обычно указатель this не используется явно. Но иногда он может быть полезен, например, при организации списков для возврата указателя ( return (this) ) или ссылки ( return* this ) на какой-то объект класса. Статическая элемент-функция класса не имеет указателя this, т.е. не связывается с конкретным объектом класса. Поэтому, для доступа к ней необходимо имя класса с операцией разрешения видимости.

Конструкторы и деструкторы. Лекция №7.


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

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

Пример:

class akt

{

int tabn;

float objem;

public: //инициализация списком //инициализация телом

akt(int x, float y): tabn(x), objem(y) //akt(int x,float y)

{} //tabn=x objem=y //{tabn=x; objem=y;}

};

main() //}

{

akt obj1(1,100000);//x=1 y=100000

}


Конструктор копирования служит для инициализации нового объекта класса значениями другого объекта того же класса, т.е. для копирования задаваемых элементов-данных одного объекта в другой. Конструктор характеризуется следующими особенностями:
  • имеет в качестве параметра либо константную ссылку на объект класса, например, const akt& obj, либо простую ссылку на объект, например, akt& objconst предпочтительней);
  • если конструктор копирования отсутствует, то компилятор генерирует конструктор по умолчанию; этот конструктор копирует все элементы-данные копируемого объекта.

Добавим в предыдущий пример конструктор копирования.

class akt main()

{ ... {

akt(const akt& obj) akt obj1(1,100000);

{ ...

tabn=obj.tabn; //копирование obj1 в obj2

objem=obj.objem; akt obj2=obj1;//или akt obj2(obj1);

} ...

}; }

Деструктор служит для уничтожения объектов класса. Деструктор характеризуется следующими свойствами:
  • имеет имя класса с префиксом-тильдой (~) и не имеет возвращаемого значения и параметров, например, ~akt();
  • автоматически вызывается компилятором при выходе из области видимости или при выполнении операции delete для объектов, размещенных в динамической памяти при помощи операции new;
  • не может быть const, static, virtual , и не наследуется.

Друзья класса


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

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

Синтаксис объявления друзей класса:

class cl1

{

friend tf1 f1(ta1 a1[,...]); //внешняя функция

friend tf2 cl3::f2(tb1 b1[,...]);//функция класса cl3

friend class cl2; //класс cl2

...

};

Друзья класса характеризуются следующими свойствами:
  • объявляются со словом friend в любой части класса;
  • могут быть дружественными более чем одному классу;
  • не могут быть взаимно друзьями; если класс cl2 является другом cl1, то это не означает, что cl1 является другом cl2;
  • дружественность не наследуется производными классами друга; если cl2 - друг cl1, то производные классы от cl2 не являются друзьями cl1;
  • дружественность не наследуется производными классами от данного класса; если cl2 - друг cl1, то это не означает, что cl2 является другом классам, производным от cl1;
  • дружественность не транзитивна; если cl2 - друг cl1, то это не означает, что друзья cl2 являются друзьями cl1.