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


Скачать 465.79 Kb.
НазваниеОбъектно-ориентированное программирование
страница1/4
Дата публикации18.03.2013
Размер465.79 Kb.
ТипДокументы
referatdb.ru > Философия > Документы
  1   2   3   4

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





  1. Раскройте смысл таких понятий объектно-ориентированного программирования, как «наследование», «инкапсуляция» и «полиморфизм» с примерами на языке С++.


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

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

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

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

Последняя определяющая характеристика традиционных объектно-ориентированных технологий – наследование. Идея проста: имея один объект, можно создать новый, автоматически поддерживающий все или некоторые «способности» старого. Следует отметить различия наследования реализации и наследование интерфейса. В первом случае объект наследует от своего родителя код. В противоположенность этому наследование интерфейса в действительности означает повторное использование спецификации – определений методов, поддерживаемых объектом. Наследование интерфейса облегчает к тому же реализацию полиморфизма.

Иногда в подклассе бывает необходимо переопределить операцию, определенную в одном из его суперклассов. Для этого операция, которая может быть получена из суперкласса в результате наследования, определяется и в подклассе; это ее повторное определение "заслоняет" ее определение в суперклассе, так что в подклассе применяется не унаследованная, а переопределенная в нем операция.

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

Для дополнения класса shape (фигура) классом circle (круг), достаточно лишь объявления его в классе shape (без изменения функций элементов класса) в модуле shape.h и скомпилировать исходный текст в shape.obj. Таким образом нет необходимости изменять исходный текст shape.c. Успешное создание потомков позволяет увеличивать программу за счет накопления уже готовых текстов программ.
Порядок вызова конструкторов и деструкторов по цепи наследования строго регламентирован. Вначале вызываются конструкторы базовых классов. Следом вызываются конструкторы производных классов. Поскольку конструкторы не наследуются, при создании производного класса наследуемые им данные-члены должны инициализироваться конструктором базового класса. Конструктор базового класса вызывается автоматически и выполняется до конструктора производного класса. Параметры конструктора базового класса указываются в определении конструктора производного класса. Таким образом происходит передача аргументов от конструктора производного класса конструктору базового класса.

Объекты класса конструируются снизу вверх: сначала базовый, потом компоненты-объекты (если они имеются), а потом сам производный класс. Уничтожаются объекты в обратном порядке: сначала производный, потом его компоненты-объекты, а потом базовый объект.

Пример.

class Basiс {

int i; // сокрытие переменной

public:

Basis(int x){ i=x; }

int GetI(void) {return I;} // получить значение скрытой переменной

void SetI(int k) {i=k;} // установить значение скрытой переменной

};
class Inherit: public Basis { // класс-наследник

int count;

public:

Inherit(int x,int c): Basis(x){ count=c; }

};


  1. ^ Специальные функции-члены класса – конструкторы, деструкторы, конструкторы копирования. Привести примеры на С++.


Как отмечалось выше объекты создаются как переменные соответствующих типов (в качастве типа указывается класс объекта):

Light lt;

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

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

  • имя конструктора совпадает с именем класса;

  • конструктор не имеет возвращаемого значения (даже void);

  • классу без конструктора предоставляется конструктор по умолчанию;

  • при явно описанном конструкторе конструктор по умолчанию не генерируется;

  • конструкторы могут быть перегружены;

  • не могут быть описаны с ключевыми словами virtual, static, const, mutable, volatile;

  • не могут явно вызываться в программе;

  • частным случаем конструктора является конструктор копирования, у которого в аргументах передается ссылка на другой объект того же класса.

Деструктор – вызывается автоматически при разрушении объекта, его задача - освободить память и корректно уничтожить объект.

  • имя деструктора также совпадает с именем класса но предваряется символом тильда "~" (~имя_класса);

  • деструктор не имеет ни какого возвращаемого значения;

  • не может быть описан как static, const, mutable, volatile;

  • без явного задания генерируется деструктор по умолчанию;

  • могут быть описаны как virtual - у всех производных классов деструкторы автоматически будут виртуальными;

  • могут явно вызываться;

Ниже приведем объявление конструктора:

ComplexType();

Определение пустого конструктора:

ComplexType() { }

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

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

ComplexType(double rePar, double imPar); /* Объявление… */

ComplexType(double rePar, double imPar) { /*…*/ } /*Определение…*/

Конструктор вызывается не для объекта класса, как другие функции-члены, а для области памяти. Для её преобразования ("превращения") в объект класса.

^ Конструктор копирования (пример):

class demo {

char *p;

public:

demo(void) { p="NULL"; }

demo(char* s){ p=s; }

demo(demo& demo_o){ p=o.p; }

void out(void){ puts(p); }

}

void main(){

demo a("Ok"), b(a);

a.out(); b.out();

}

Вместе с конструктором умолчания, конструктор копирования входит в обязательный набор конструкторов для любого класса. Реализация механизма копирования значений для транслятора не является неразрешимой задачей. Конструктор копирования всего лишь создаёт копии объектов. Этот процесс реализуется при помощи стандартного программного кода. И построить такой код транслятор способен самостоятельно. Здесь и далее, в примерах нами будет применяться операция присвоения = . В определённом смысле эта операция подобна конструктору. Реализующий эту операцию код автоматически создаётся на этапе трансляции для любого класса. Как и генерация кода стандартных конструкторов, это не самая сложная задача.

Чтобы восстановить структуру заголовка конструктора копирования, мы должны лишь определить тип его параметра. На первый взгляд, здесь всё просто. В качестве значения параметра конструктору передаётся имя объекта, значит можно предположить, что тип параметра конструктора копирования соответствует данному классу. Однако это не так. И вот почему. В C++ конструктор копирования является единственным средством создания копий объекта. На самом деле, в конструкторе копирования класса X в качестве параметра используется ссылка на объект этого класса. Причём эта ссылка объявляется со спецификатором const. Как известно, выражение вызова функции с параметром типа X ничем не отличается от выражения вызова функции, у которой параметром является ссылка на объект типа X. При вызове такой функции не приходится копировать объекты как параметры. Передача адреса не требует копирования объекта, а значит, при этом не будет и рекурсии.

Конструктор копирования - обязательный элемент любого класса. Он также может быть переопределён подобно конструктору умолчания. Спецификатор const (конструктор копирования работает с адресом объекта) предохраняет объект-параметр от случайной модификации в теле конструктора

Операторы new и delete предназначены для динамического распределения памяти и могут использоваться в С++ - программах вместо функций malloc() и free().

Оператор new имеет два допустимых формата вызова:

[::] new [список_аргументов] тип [инициализатор]

[::] new [список_аргументов] (тип) [инициализатор]

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

инициализатор - значение, используемое для инициализации данных в памяти.

Пример использования оператора new:

double *p,*p2,*p3,*p4;

p=new double;

p2=new double(1.2);

p3=new double[1];

p4=new double[1](3.14); // некорректно, массивы не могут

//инициализироваться по new

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

delete p;

delete[] p3;

Для удаления элементов классов вызывается деструктор. В некоторых реализациях языка вызов оператора delete для несуществующего или пустого указателя приводит к возникновению исключения.


  1. ^ Перегрузка и переопределение функций и операторов в С++. Привести примеры кода.


Одним из подходов реализации принципа полиморфизма в языке С++ является использование переопределения функций. В С++ две и более функций могут иметь одно и то же имя. Компилятор С++ оперирует не исходными именами функций, а их внутренними представлениями, которые существенно отличаются от используемых в программе. Эти имена содержат в себе скрытое описание типов аргументов. С этими же именами работают программы компоновщика и библиотекаря. По этой причине мы можем использовать функции с одинаковыми именами, только типы аргументов у них должны быть разными. Именно на этом и основана реализация одной из особенностей полиморфизма. Заметим, что компилятор не различает функции по типу возвращаемого значения. Поэтому для компилятора функции с различным списком аргументов – это разные функции, а с одинаковым списком аргументов, но с разными типами возвращаемого значения - одинаковые. Для корректной работы программ последнего следует избегать. Рассмотрим простой пример переопределения функции sum, выполняющей сложение нескольких чисел различного типа.

#include "iostream.h"

class cls

{ int n;

double f;

public:

cls(int N,float F) : n(N),f(F) {}

int sum(int); // функция sum с целочисленнным аргументом

double sum(double); // функция sum с дробным аргументом

void see(); // вывод содержимого объекта

};

int cls:: sum(int k)

{ n+=k;

return n;

}

double cls:: sum(double k)

{ f+=k;

return f;

}

void cls:: see()

{cout <void main()

{ cls obj(1,2.3);

obj.see(); // вывод содержимого объекта

cout <
cout <
}

Результат работы программы:

1 2.3

2

3.3

В тоже время переопределение функций может создавать проблему двусмысленности. Например:

class A

{ . . .

public:

void fun(int i,long j) {cout<
void fun(long i,int j) { cout<
};
main()

{ A a;

a.fun(2,2); // ошибка неизвестно какая из 2 функций вызывается

}

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

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

тип_возвр_значения operator знак_операции (специф_параметров)

{операторы_тела_функции}

^ Перегрузка унарных операций. Любая унарная операция  может быть определена двумя способами: либо как компонентная функция без параметров, либо как глобальная функция с одним параметром. В первом случае выражение Z означает вызов Z.operator (), во втором  вызов operator(Z). Вызываемый объект класса автоматически воспринимается как операнд.

Пример.

class audio_player {

int records_count;

int current_record;

...

public:

play(int i);

void init(void){ current_record = 0; }

void operator++ (){ //++a

current_record++;

if(current_record>records_count) current_record = 0;}

void operator++ (int i){ //a++

current_record++;

if(current_record>records_count) current_record = 0;}

void operator—(){ //--a

current_record--;

if(current_record<0) current_record = records_count - 1;}

} ;

void main(){

audio_plajer a;

a.init();

++a;

a++;

}
  1   2   3   4

Похожие рефераты:

Программа вступительного экзамена по специальности 05. 13. 18 Математическое...
«Объектно-ориентированное программирование», «Вычислительные системы и сети», «Системное программирование», «Операционные системы...
Учебная программа по дисциплине Объектно-ориентированное программирование...
Основной целью преподавания дисциплины «Объектно-ориентирован­ное программирование» является обучение слушателей современным мето­дам...
Учебная программа по дисциплине Объектно-ориентированное программирование...
Основной целью преподавания дисциплины «Объектно-ориентирован­ное программирование» является обучение слушателей современным мето­дам...
Вопросы к экзамену по дисциплине «Объектно-ориентированное программирование»
Вопросы к экзамену по дисциплине «Объектно-ориентированное программирование» по специальности 1-40 01 02 «Информационные системы...
Вопросы к экзамену по дисциплине «Объектно-ориентированное программирование»
Вопросы к экзамену по дисциплине «Объектно-ориентированное программирование» по специальности 1-40 01 02 «Информационные системы...
Информационные системы
Объектно-ориентированное программирование в разработке информационных систем (С++)
Методические указания к курсовой работе по дисциплине «Объектно-ориентированное...
Приводится краткое изложение ключевых понятий дисциплины и описание нотации языка uml, достаточной для изображения диаграмм классов,...
Методические рекомендации по изучению дисциплины по дисциплине «Объектно-ориентированное...
Эволюция технологий программирования. Основные принципы структурного и объектно-ориентированного программирования. Описание терминов...
Вопросы к экзамену по дисциплине «Объектно-ориентированное программирование»
Состав языка Си:, идентификаторы,, знаки операций, константы, комментарии. Лексемы
Вопросы к зачету по дисциплине “Объектно-ориентированное программирование”
Лексемы языка С++ (ключевые слова, идентификаторы, литералы, операторы, знаки пунктуации)

Вы можете разместить ссылку на наш сайт:
Школьные материалы


При копировании материала укажите ссылку © 2013
контакты
referatdb.ru
referatdb.ru
Рефераты ДатаБаза