Лекции по основам программирования на C/C++

Вид материалаЛекции

Содержание


Рекурсивные функции.
Лекция 17.Принципиальные особенности программирования в среде MS DOS и Windows
Подобный материал:
1   2   3   4   5   6

Лекция 16. Использование виртуальных методов

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



В программе объекты этих классов могут быть объявлены, например, таким образом.
A object_A; //объявление объекта типа А
B object_B; //объявление объекта типа В
C object_C; //объявление объекта типа С
Согласно данному правилу указатель типа А может ссылаться на любой из этих трех объектов. То есть ,вот это будет верным:
A *point_to_Object; // объявим указатель на базовый класс
point_to_Object=&object_C; //присвоим указателю адрес объекта С
point_to_Object=&object_B; //присвоим указателю адрес объекта В
А вот это уже не правильно:
В *point_to_Object; // объявим указатель на производный класс
point_to_Object=&object_А; //нельзя присвоить указателю адрес базового объекта
Несмотря на то, что указатель point_to_Object имеет тип А*, а не С* (или В*), он может ссылаться на объекты типа С (или В). Может быть правило будет более понятным, если вы будете думать об объекте С, как особом виде объекта А. Ну, например, курица - это особая разновидность птиц, но она все таки остается птицей, хоть и не летает. Конечно, эта взаимосвязь объектов и указателей работает только в одном направлении. Объект типа С - особый вид объекта А, но вот объект А не является особым видом объекта С. Возвращаясь к курице смело можно сказать, что если бы все птицы были особым видом кур - они бы просто не умели летать!
Этот принцип становится особенно важным, когда в классах, связанных наследованием определяются виртуальные методы. Виртуальные методы имеют точно такой же вид и программируются так же, как и самые обычные методы. Только их объявление производится с ключевым словом virtual. Например, наш базовый класс А может объявить виртуальный метод class A
{
public:
virtual void v_function(void);//метод описывает некое поведение объектов //класса А
};
В классе может объявляться столько виртуальных методов сколько вам потребуется. И находится они могут в любой части класса - закрытой, открытой или защищенной.
Если в классе В, порожденном от класса А нужно описать какое-то другое поведение, то можно объявить виртуальный метод, названный опять-таки v_function().
class B: public A
{
public:
virtual void v_function(void);//замещающий метод описывает некое
//новое поведение класса В
};
Когда в классе, подобном В, определяется виртуальный метод, имеющий одинаковое имя с виртуальным методом класса-предка, такой метод называется замещающим. Виртуальный метод v_function() в В замещает виртуальный метод с тем же именем в классе А.

Ну, а теперь самое важное!
Вернемся к указателю point_to_Object типа А*, который ссылается на объект object_В типа В*. Давайте внимательно посмотрим на оператор, который вызывает виртуальный метод v_function()для объекта, на который указывает point_to_Object.

A *point_to_Object; // объявим указатель на базовый класс
point_to_Object=&object_B; //присвоим указателю адрес объекта В
point_to_Object->v_function(); //вызовем метод

Указатель point_to_Object может хранить адрес объекта типа А или В. Значит во время выполнения этот оператор point_to_Object-gt;v_function(); вызывает виртуальный метод класса, на объект которого он в данный момент ссылается. Если point_to_Object ссылается на объект типа А, вызывается метод, принадлежащий классу А. Если point_to_Object ссылается на объект типа В, вызывается метод, принадлежащий классу В. Итак, один и тот же оператор вызывает метод класса адресуемого объекта. Это и есть действие, определяемое во времени выполнения.

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

Рассмотрим более подробно организацию и работу рекурсивных подпрограмм.

Рекурсию можно использовать для вычисления факториала n!. Чтобы найти n!, нужно определить (n-1)!. А для этого необходим (n-2)! и так далее.

#include

#include

int z;

int Fact(int n)

{

if (n == 1) return 1;

else return Fact(n - 1) * n; }

main()

{ int n;

printf("Число? \n");

scanf("%d",&n);

z = Fact(n); printf("%d",z);

}


^ Лекция 17.Принципиальные особенности программирования в среде MS DOS и Windows

Поговорим о принципиальных особенностях программирования в среде MS DOS и Windows.

Значительная часть времени в программировании уходит на про-граммирование внешних устройств. Причем под внешними устройствами понимается и работа с памятью, файловой системой, дисплеем, клавиатурой, мышью и т.д. Основным отличием операционной системы Windows от MS DOS является то, что управление всеми внешними устройствами Windows берет на себе. Ниже на рисунке представлена схема взаимодействия приложения с внешними устройствами в системах MS DOS и Windows



Внешние устройства







MS DOS






Прямое обращение к ВУ

Приложение




Системные вызовы







Внешние устройства







Windows

Системные вызовы (API-функции)






Приложение




Беря на себя взаимодействие с внешними устройствами Windows позволяет создавать более надежное и совместимое программное обеспечение.

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

Еще одной особенностью програмирования в среде Windows является присутствие только одной модели памяти. в Windows используется так называемая линейная или плоская модели памяти. Суть этой модели заключается в том, что содержание всех сегментных регистров фиксируется, а адресация осуществляется с помощью 32-битных регистров. Такая модель основывается на так называемой страничной адресации в защищенном режиме. Для программирования это дает значительные преимущества, заключающиеся в том, что поскольку сегментом теперь является вся память, то снимаются все ограничения на размер кода, данных, стека и объема отводимого под локальные переменные.


Литература:

1. Б. Керниган, Д. Ритчи. Язык программирования Си. - М.: Финансы и статистика, 1992.

2. Страуструп Б. Язык программирования СИ++. - М.: Радио и связь,1991.­352с.

3. Ричард Вайнер, Льюс Пинсон С++ изнутри. - Киев: ДиаСофт,1993.

4. Е.И. Козелл,Л.Ь. Романовская, т,В. Русс и др. От С к С++. М., Финансы и статистика, 1993

5. Шилд Г. Программирование на С и С++ для WINDOWS 95.-К.:Торгово- издательское бюро BHV, 1996.-400с.

6. Шилд Герберт. Самоучитель С++.-BHV.-С.-Петербург.,1997.