пользователей: 21222
предметов: 10454
вопросов: 177450
Конспект-online
зарегистрируйся или войди через vk.com чтобы оставить конспект.
РЕГИСТРАЦИЯ ЭКСКУРСИЯ

13.Языки программирования С и С++. Реализация объектной модели в С++. Шаблоны функции. Пример использования шаблонов для реализации сортировки Хоара. Производные классы. Наследование: одиночное и множественное. Полиморфизм в С++. Виртуальные функции и классы. Абстрактные классы. Примеры.

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

Например:

extern void swap(int*, int*);    // описание

void swap(int*, int*)            // определение

/**

  int t = *p;

  *p =*q;

  *q = t;

**/

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

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

int foo(int n);

Этот прототип объявляет функцию с именем «foo», которая принимает один аргумент «n» целого типа и возвращает целое число. Определение функции может располагаться где угодно в программе, но объявление требуется только в случае её использования.

Рекурсией называется вызов функции из самой себя.Функции, которые во время выполнения вызывают сами себя называют рекурсивными.Рекурсия бывает прямой и косвенной.Прямая рекурсия – это если функция содержит в своем теле вызов самой себяКосвенная рекурсия – это если первая функция вызывают вторую функцию, но при этом в теле второй функции прописан вызов первой.

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

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

Например, объявление:

int (*fun) (double, double);задает указатель с именем fun на функцию, возвращающую значение типа int и имеющую два аргумента типа double.


 

typedef void (*PF)(void); //Это для ссылки на функцию

// Есть класс:

class MyClass

/**

public:

void func1(void)/** **/

void func2(void)/** **/

 PF massiv[2]; // создаем массив ссылок для функций

MyClass(void) // Конструктор

/**

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

massiv[0]=&func1;

massiv[1]=&func2;

**/

/**;

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

//параметризованная функция быстрой сортировки Хоара

template <class Type>

void qs(Type *a, int left, int right)

/**        int i, j;                   //левая и правая границы массива

                Type x, y;

                i = left; j = right;

                x = a[(left+right)/2];  //определим "центр" массива

                do

                /**        while(a[i]<x && i<right) i++;

                               while(x<a[j] && j>left) j--;

                               if(i<=j)

                               /**        y=a[i]; a[i]=a[j]; a[j]=y;

                                               i++; j--;                 **/        **/

                while (i<=j);

                if (left<j) qs(a, left, j);  //рекурсивный вызов для левой части

                if (i<right) qs(a, i, right);//рекурсивный вызов для правой части

/**

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

При наследовании важную роль играет статус доступа к компонентам класса.

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

Class имя : /**private или public**/ имя_1, имя_2, …, имя_N

/**

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

**/

Наследование

При создании объекта производного класса сначала вызываются конструкторы базовых классов, а потом – конструктор производного. Деструкторы вызываются в обратном порядке. При наследовании статус доступа к полям и собственным функциям базового класса изменяется следующим образом: если перед базовым классом указан атрибут private, то:открытые члены базового класса переходят в закрытые в производном классе, защищенные – в закрытые, закрытые – в недоступные. Если перед базовым классом используется атрибут public, то:открытые члены базового класса переходят в открытые в производном  классе, защищенные – в защищенные, закрытые – в недоступные.

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

Виртуальные классы

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

сlass имя_производного_класса:

virtual public имя_виртуального_базового_класса

/**

тело производного класса;

**/

Виртуальные функции

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

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

virtual тип_возвращаемого_значения  имя(параметры) Виртуальные составные функции позволяют выбирать члены класса с одним и тем же именем через указатель функции в зависимости от типа указателя.В частности, если в примере в базовом классе указать

                               virtual void show(), а остальной текст оставить без изменения, то программа выведет слова «яблоки» и «апельсины».Функция, объявленная, но не определенная в базовом классе, называется чисто виртуальной. Чисто виртуальная функция должна быть переопределена в каком-нибудь из производных классов. В базовом классе она объявляется с помощью оператораvirtual тип_возвр_значения имя(параметры) = 0;

Например,

Class Figure

                               /**        int color;

                               public:

                                               virtual void show();

                           */;

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


10.06.2015; 17:44
хиты: 126
рейтинг:0
для добавления комментариев необходимо авторизироваться.
  Copyright © 2013-2016. All Rights Reserved. помощь