- •Билет № 3
- •Базовые конструкции структурного программирования
- •Процессы в Windows
- •Билет № 6
- •Объектно-ориентированное программирование
- •Критические секции
- •Void InitializeCriticalSection(lpcritical_section lpCriticalSection); // вход в критическую секцию
- •Задача. Произвести инверсию (перестановка наоборот) массива
- •Билет № 9
- •Простое наследование
- •События
- •Задача. Отсортировать массив методом выбора минимального элемента.
- •Билет № 12
- •Абстрактные классы
- •Void Print(void) /* аспект виртуальной функции*/
- •Void Print(void) /* аспект виртуальной функции*/
- •Исключения и их обработчики
- •Задача. Ввести с клавиатуры два вещественных числа и определить наибольшее из них.
- •Билет № 15
- •Назначение операционной системы
- •Резервирование, распределение и освобождение виртуальной памяти
- •Int *a; // указатель на массив целых чисел
- •Задача. Ввести целое число и определить, сколько в нем цифр.
Критические секции
В операционных системах Windows проблема взаимного исключения для параллельных потоков, выполняемых в контексте одного процесса, решается при помощи объекта типа critical_section, который не является объектом ядра операционной системы. Для работы с объектами типа critical_section используются следующие функции:
// инициализация критической секции
Void InitializeCriticalSection(lpcritical_section lpCriticalSection); // вход в критическую секцию
VOID EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
// попытка войти в критическую секцию
BOOL TryEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
// выход из критической секции
VOID LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
// разрушение объекта критическая секция
VOID DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
Каждая из этих функций имеет единственный параметр, указатель на объект типа CRIТ 1C AL_S ЕС ТI ON. Все ЭТИ фуНКЦИИ, за исключением TryEnterCriticalSection, не возвращают значения. Функция TryEnterCriticalSection возвращает ненулевое значение, если поток вошел в критическую секцию или уже находится в ней, в противном случае функция возвращает значение false. Отметим также, ЧТО функция TryEnterCriticalSection поддерживается только операционной системой Windows 2000.
Пример работы несинхронизированных потоков
#include <windows.h>
#include <iostream.h>
DWORD WINAPI thread(LPVOID)
{
int i,j;
for (j = 0; j < 10; ++j)
{
// выводим строку чисел j for (i = 0; i < 10; ++i)
{
cout « j « ' ' « flush;
Sleep(17);
}
cout « endl;
return 0;
}
int main()
{
int i, j ;
HANDLE hThread;
DWORD IDThread;
hThread=CreateThread(NULL/ 0; thread, NULL, 0, &IDThread); if (hThread == NULL) return GetLastError();
for (j = 10; j < 20; ++j)
{
for (i = 0; i < 10; ++i)
{
// выводим строку чисел j cout « j « ' ' « flush;
Sleep(17);
}
cout « endl;
}
// ждем, пока поток thread закончит свою работу WaitForSingleObject(hThread, INFINITE);
return 0;
}
Задача. Произвести инверсию (перестановка наоборот) массива
#include <iostream>
#include <time.h>
#include <stdlib.h>
const int N = 10;
int main(int argc, char** argv) {
srand(time(0));
int i, A[N], c;
for ( i = 0; i < N; i ++ ){
A[i] = rand()%100;
printf("%d ", A[i]);
}
printf("\n ");
for ( i = 0; i < N/2; i ++ )
{
c = A[i];
A[i] = A[N-1-i];
A[N-1-i] = c;
}
printf("\n Result:\n");
for ( i = 0; i <N; i ++ )
printf("%d ", A[i]);
return 0;
}
Билет № 9
Простое наследование
Наследованием называют конструирование новых более сложных производных классов (классов-потомков) из уже имеющихся базовых классов (классов-родителей) посредством добавления полей и методов. Это – эффективное средство расширения функциональных возможностей существующих классов без их перепрограммирования и повторной компиляции существующих программ.
По определению компонентами производного класса являются:
компоненты базового класса, за исключением конструктора, деструктора и компонентной функции, переопределяющей операцию «присваивания» (=);
компоненты, добавляемые в теле производного класса.
В функциональном смысле производные классы являются более мощными по отношению к базовым классам, так как, включая поля и методы базового класса, они обладают еще и своими компонентами.
Ограничение доступа к полям и функциям базового класса при наследовании осуществляется с помощью специальных описателей, определяющих вид наследования:
class <Имя производного класса >:
<Вид наследования> <Имя базового класса> {<Тело класса>};
Где вид наследования определяется ключевыми словами: private, protected,
Public.
Видимость полей и функций базового класса из производного определяется секцией, в которой находится объявление компонента и видом наследования. Если вид наследования явно не указан, то по умолчанию принимается private.
Однако хороший стиль программирования требует, чтобы в любом случае вид наследования был задан явно.
самым простым является наследование вида public (общедоступное), однако при его применении следует помнить, что скрытые в секции private компоненты базового класса в производном все равно недоступны. Соттветственно для обращения к скрытым полям базового класса должны использоваться методы общедоступной или защищенных секций базового класса, например:
Class A
{
int x;
public:
void set_a(int ax){x=ax;}
print_a(){cout<<x;}
};
class B:public A
{
int y;
public:
void set_b(int ax,int bx)
{
set_a(ax); // доступ к скрытому полю x
b=bx;
}
print_b()
{
print_a(); // доступ к скрытому полю x
cout<<y;
}
};
