Помощь в написании студенческих работ
Антистрессовый сервис

Конструирование программ

КонтрольнаяПомощь в написанииУзнать стоимостьмоей работы

То есть, в случае виртуальной функции, для определения реализации функции используется информация о типе объекта и вызывается «правильная» реализация, независимо от типа указателя. При вызове невиртуальной функции, компилятор руководствуется типом указателя или ссылки, поэтому вызываются две разные реализации function2 (), несмотря на то, что используется один и тот же объект. Конструирование… Читать ещё >

Конструирование программ (реферат, курсовая, диплом, контрольная)

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

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

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

Базовый класс может и не предоставлять реализации виртуального метода, а только декларировать его существование. Такие методы без реализации называются «чистыми виртуальными» (перевод англ. pure virtual) или абстрактными. Класс, содержащий хотя бы один такой метод, тоже будет абстрактным. Объект такого класса создать нельзя (в некоторых языках допускается, но вызов абстрактного метода приведёт к ошибке). Наследники абстрактного класса должны предоставить реализацию для всех его абстрактных методов, иначе они, в свою очередь, будут абстрактными классами.

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

Пример виртуальной функции на C++

Пример на C++, иллюстрирующий отличие виртуальных функций от невиртуальных:

class Ancestor

{

public:

virtual void function1 () {cout << «Ancestor:function1 ()» << endl;}

void function2 () {cout << «Ancestor:function2 ()» << endl;}

};

class Descendant: public Ancestor

{

public:

virtual void function1 () {cout << «Descendant:function1 ()» << endl;}

void function2 () {cout << «Descendant:function2 ()» << endl;}

};

Descendant* pointer = new Descendant ();

Ancestor* pointer_copy = pointer;

pointer->function1 ();

pointer->function2 ();

pointer_copy->function1 ();

pointer_copy->function2 ();

В этом примере класс Ancestor определяет две функции, одну из них виртуальную, другую — нет. Класс Descendant переопределяет обе функции. Однако, казалось бы одинаковое обращение к функциям даёт разные результаты. На выводе программа даст следующее:

Descendant:function1 ()

Descendant:function2 ()

Descendant:function1 ()

Ancestor:function2 ()

То есть, в случае виртуальной функции, для определения реализации функции используется информация о типе объекта и вызывается «правильная» реализация, независимо от типа указателя. При вызове невиртуальной функции, компилятор руководствуется типом указателя или ссылки, поэтому вызываются две разные реализации function2 (), несмотря на то, что используется один и тот же объект.

Следует отметить, что в С++ можно, при необходимости, указать конкретную реализацию виртуальной функции, фактически вызывая её невиртуально:

pointer->Ancestor:function1 ();

для нашего примера выведет Ancestor: function1 (), игнорируя тип объекта.

Пример виртуальной функции в Delphi

Язык Object Pascal, использующийся в Delphi, тоже поддерживает полиморфизм. Рассмотрим пример:

Объявим два класса. Предка (Ancestor):

TAncestor = class

private

protected

public

{Виртуальная процедура.}

procedure VirtualProcedure; virtual;

procedure StaticProcedure;

end;

и его потомка (Descendant):

TDescendant = class(TAncestor)

private

protected

public

{Перекрытие виртуальной процедуры.}

procedure VirtualProcedure; override;

procedure StaticProcedure;

end;

Как видно в классе предке объявлена виртуальная функция — VirtualProcedure. Чтобы воспользоваться достоинствами полиморфизма, её нужно перекрыть в потомке.

Реализация выглядит следующим образом:

{TAncestor}

procedure TAncestor. StaticProcedure;

begin

ShowMessage ('Ancestor static procedure.');

end;

procedure TAncestor. VirtualProcedure;

begin

ShowMessage ('Ancestor virtual procedure.');

end;

{TDescendant}

procedure TDescendant. StaticProcedure;

begin

ShowMessage ('Descendant static procedure.');

end;

procedure TDescendant. VirtualProcedure;

begin

ShowMessage ('Descendant override procedure.');

end;

Посмотрим как это работает:

procedure TForm2. BitBtn1Click (Sender: TObject);

var

MyObject1: TAncestor;

MyObject2: TAncestor;

begin

MyObject1:= TAncestor. Create;

MyObject2:= TDescendant. Create;

try

MyObject1. StaticProcedure;

MyObject1. VirtualProcedure;

MyObject2. StaticProcedure;

MyObject2. VirtualProcedure;

finally

MyObject1. Free;

MyObject2. Free;

end;

end;

Заметьте, что в разделе var мы объявили два объекта MyObject1 и MyObject2 типа TAncestor. А при создании MyObject1 создали как TAncestor, а MyObject2 как TDescendant. Вот что мы увидим при нажатии на кнопку BitBtn1:

1. Ancestor static procedure.

2. Ancestor virtual procedure.

3. Ancestor static procedure.

4. Descendant override procedure.

Для MyObject1 все понятно, просто вызвались указанные процедуры. А вот для MyObject2 это не так.

Вызов MyObject2. StaticProcedure; привел к появлению «Ancestor static procedure.». Ведь мы объявили MyObject2: TAncestor, поэтому и была вызвана процедураStaticProcedure; класса TAncestor.

А вот вызов MyObject2. VirtualProcedure; привел к вызову VirtualProcedure; реализованной в потомке (TDescendant). Это произошло потому, что MyObject2 был создан не какTAncestor, а как TDescendant: MyObject2:= TDescendant. Create; И виртуальный метод VirtualProcdure был перекрыт.

В Delphi полиморфизм реализован с помощью так называемой виртуальной таблицы методов (или VMT).

Достаточно часто виртуальные методы забывают перекрыть с помощью ключевого слова override. Это приводит к закрытию метода. В этом случае замещения методов в VMT не произойдет и требуемая функциональность не будет получена.

Эта ошибка отслеживается компилятором, который выдаёт соответствующее предупреждение.

Вызов метода предка из перекрытого метода

Бывает необходимо вызвать метод предка в перекрытом методе.

Объявим два класса. Предка (Ancestor):

TAncestor = class

private

protected

public

{Виртуальная процедура.}

procedure VirtualProcedure; virtual;

end;

и его потомка (Descendant):

TDescendant = class(TAncestor)

private

protected

public

{Перекрытие виртуальной процедуры.}

procedure VirtualProcedure; override;

end;

Обращение к методу предка реализуется с помощью ключевого слова «inherited»

procedure TDescendant. VirtualProcedure;

begin

inherited;

end;

Стоит помнить, что в Delphi деструктор должен быть обязательно перекрытым — «override» — и содержать вызов деструктора предка

TDescendant = class(TAncestor)

private

protected

public

destructor Destroy; override;

end;

destructor TDescendant. Destroy;

begin

inherited;

end;

В языке C++ не нужно вызывать конструктор и деструктор предка, деструктор должен быть виртуальным. Деструкторы предков вызовутся автоматически. Чтобы вызвать метод предка, нужно явно вызвать метод:

class Ancestor

{

public:

virtual void function1 () {printf («Ancestor:function1»);}

};

class Descendant: public Ancestor

{

public:

virtual void function1 () {

printf («Descendant:function1»);

Ancestor:function1 (); // здесь будет напечатано «Ancestor:function1»

}

};

Для вызова конструктора предка нужно указать конструктор:

class Descendant: public Ancestor

{

public:

Descendant (): Ancestor ();

};

Задание 2

Значение аргумента х изменяется от, а до b с шагом h. Для каждого x найдите значение функции Y (x) суммы S (x) и |Y (x) — S (x)| и выведите в виде таблицы. Значения a, b, h введите с клавиатуры произвольно. Вычисление Y (x) и S (x) реализуйте в виде функций.

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

Текст программы

#include

#include

#include

#include

#pragma hdrstop

#include «Unit2.h»

#pragma package (smart_init)

typedef double (*TFun) (double);

double funY (double);

double funS (double);

double funDYS (double);

void Out_Tabl (TFun, double, double, double);

void main ()

");

Out_Tabl (funDYS, a, b, h);

puts («n Press any key…»);

getch ();

double funY (double x)

{

return cos (x);

}

double funS (double x)

{

double s=1, a=1;

for (int k=1; k<=20; k++)

{

a=-a*x*x/((2*k-1)*(2*k));

s+=a;

}

return s;

}

double funDYS (double x)

{

return fabs (funS (x) — funY (x));

}

void Out_Tabl (TFun f, double xn, double xk, double h)

{

for (double x=xn; x<=xk; x+=h)

printf («x =%5.2lf, y =%8.4lfn», x, f (x));

}

Результат выполнения программы

Задание 3

Разработайте программу обработки массивов. Входные данные введите с клавиатуры. Результаты работы программы отобразите на экране.

Дана целочисленная квадратная матрица порядка N. Найдите номера строк, элементы в каждой из которых одинаковы.

Текст программы

#include

#pragma hdrstop

#include «Unit3.h»

#pragma package (smart_init)

#include

#include

#include

void main ()

{

int a[20] [20];

int i, j, n=0, k;

while (n<1 || n>20) {

cout<< «N=»;

cin>>n;

}

cout<< «Input matrix A (NxN):n»;

for (i=0; i

for (j=0; j

cin>>a[i] [j];

cout<<�"nRaws with equals elements: n";

for (i=0; i

k=0;

for (j=1; j

if (a[i] [j]==a[i] [0]) k++;

if (k==n-1) cout<<�"n";

}

cout<<�"nPress any key…";

while (! kbhit ());

}

Результат выполнения программы

Задание 4

виртуальный класс программа массив

Разработайте программу работы со строками. Организуйте ввод исходных данных с клавиатуры. Используйте функции из библиотеки обработки строк string.h. Результаты работы программы отобразите на экране.

Дана строка произвольной длины. Группы символов, разделенные пробелами (од-ним или несколькими), будем называть словами. Определите в соответствии с вариантом:

Вариант 8

Количество слов в строке, а также самое короткое слово (если несколько слов имеют минимальную длину, то возьмите первое из них).

Текст программы

#include

#include

#include

#include

void main ()

{

clrscr ();

char string[100];

char *word, minword[50];

int k=0;

cout<<�"n";

cout<< «Input string:»;

cin.getline (string, 100);

cout<<�"n";

cout<< «Words:n»;

word=strtok (string, ««);

while (word≠ NULL)

{

k++;

cout<<�"n";

if (k==1) strcpy (minword, word);

else

if (strlen (word)

word = strtok (NULL, ««);

}

cout<<�"nNumber of words is equal to «<

cout<<�"nShortest word in string: «<<�"n»;

getch ();

}

Результат выполнения программы

Задание 5

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

— фамилия и инициалы;

— дата рождения;

— номер группы;

— оценки за семестр по предметам: физика, математика, информатика, этика, психология.

Организуйте ввод исходных данных, средний балл каждого учащегося рассчитайте по введенным оценкам. На экране отобразите всю введенную информацию и осуществите поиск данных в соответствии с вариантом.

Выведите анкетные данные учащихся, имеющих средний балл выше общего среднего балла всех учащихся.

Текст программы

#include

#pragma hdrstop

#include

#include

struct TZap

{char FIO[30];

int year, group, fiz, mat, inf, eti, psi;

double s_b;

} Zap;

int size = sizeof (TZap);

FILE *Fz, *Ft;

char File_Zap[] = «zapisi.dat»;

char File_Rez[] = «rezult.txt»;

void Out (TZap);

void main ()

{

int kod, D_f, i=0, j, kol, ng;

long len;

double sum=0;

TZap st, *mas_Z;

Ft = fopen (File_Rez, «w»);

while (true)

{

puts («n Actions: Create-1 Insert-2 View-3 Info-4 Exit-0»);

scanf («%d», &kod);

switch (kod)

{

case 1:

if ((Fz=fopen (File_Zap, «wb»))==NULL)

{

puts («n Create ERROR!»);

return;

}

fclose (Fz);

printf («n Create New File % s! n», File_Zap);

break;

case 2:

Fz = fopen (File_Zap, «ab»);

printf («n F.I.O. -«);

fflush (stdin);

gets (Zap.FIO);

printf («Year -«);

scanf («%d», &Zap.year);

printf («Group -«);

scanf («%d», &Zap.group);

printf («Phisics -«);

scanf («%d», &Zap.fiz);

printf («Mathematics -«);

scanf («%d», &Zap.mat);

printf («Informatics -«);

scanf («%d», &Zap.inf);

printf («Etika -«);

scanf («%d», &Zap.eti);

printf («Psihology -«);

scanf («%d», &Zap.psi);

Zap.s_b=(Zap.fiz+Zap.mat+Zap.inf+Zap.eti+Zap.psi)/5.;

fwrite (&Zap, size, 1, Fz);

fclose (Fz);

break;

case 3:

Fz = fopen (File_Zap, «rb»);

D_f = fileno (Fz);

len = filelength (D_f);

kol = len/size;

mas_Z = new TZap[kol];

for (i=0; i < kol; i++)

fread ((mas_Z+i), size, 1, Fz);

fclose (Fz);

printf («nt — List of studentsn»);

fprintf (Ft, «nt — List of studentsn»);

// вывод полного списка

for (i=0; i

Out (mas_Z[i]);

printf («n»);

fprintf (Ft, «n»);

delete [] mas_Z;

break;

case 4:

Fz = fopen (File_Zap, «rb»);

D_f = fileno (Fz);

len = filelength (D_f);

kol = len/size;

mas_Z = new TZap[kol];

for (i=0; i

fread ((mas_Z+i), size, 1, Fz);

sum+=mas_Z[i]. s_b;

}

fclose (Fz);

sum=sum/kol;

printf («nAverage score =%6.3lfn», sum);

printf («nt — Students with midscore more then averagen»);

fprintf (Ft, «nt — Students with midscore more then averagen»);

// вывод учащихся со средним баллом выше среднего

for (i=0; i

if (mas_Z[i]. s_b > sum)

Out (mas_Z[i]);

printf («n»);

fprintf (Ft, «n»);

delete [] mas_Z;

break;

case 0:

fclose (Ft);

return;

}

}

}

void Out (TZap z)

{

printf («n % 20s, %5d, %5d, %3d, %3d, %3d, %3d, %3d, %6.3lf»,

z.FIO, z. year, z. group, z. fiz, z. mat, z. inf, z. eti, z. psi, z. s_b);

fprintf (Ft, «n % 20s, %5d, %5d, %3d, %3d, %3d, %3d, %3d, %6.3lf»,

z.FIO, z. year, z. group, z. fiz, z. mat, z. inf, z. eti, z. psi, z. s_b);

}

Результат выполнения программы

Задание 6

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

Имя класса и его атрибуты выберите в соответствии с вариантом.

Класс Спортсмен с атрибутами Фамилия и инициалы, Вид спорта, Возраст.

Текст программы

#include

#pragma hdrstop

#include

#include

class SportsMan

{

private:

char* name; // фамилия и инициалы

char* kind; // вид спорта

int age; // возраст

public:

// Конструктор

SportsMan (char* aName, char* aKind, int aAge)

{

name = aName;

kind = aKind;

age = aAge;

}

// Деструктор

~SportsMan ()

{

delete name;

delete kind;

}

void print ()

{

cout<<�" Kind: «<<�» Age: «<

cout<

cout<<�" -«;

cout<

}

};

int main ()

{

clrscr ();

// создание объектов

SportsMan obj1 («Alla Kruglova», «hockey», 27);

SportsMan obj2 («Mexail Krogak», «football», 23);

// выделяем память в динамической области

SportsMan* obj3 = new SportsMan («Andrey Sobchak», «box», 12);

SportsMan* obj4 = new SportsMan («Masha Suslikova», «fighting», 73);

// вызов метода класса через имя объекта

obj1.print ();

obj2.print ();

// вызов метода класса через указатель на объект

obj3->print ();

obj4->print ();

// Очищаем память;

// obj1 и obj2 — автоматические переменные, и их не нужно

// самостоятельно удалять

delete obj3;

delete obj4;

getch ();

return 0;

}

Результат выполнения программы

виртуальный класс программа массив

1. Свободная энциклопедия http://ru.wikipedia.org

2. Демидович Е. М. Основы алгоритмизации и программирования. Язык Си: Пособие для студентов БГУИР / Е. М. Демидович. — Мн.: Бестпринт, 2004. — 384 с.

3. Касаткин, А. И. Профессиональное программирование на языке СИ: от Турбо-С до Borland С++: справочное пособие / А. И. Касаткин, А. Н. Вольвачев. — Минск: Выш. шк., 1992.

4. Конструирование программ и языки программирования: учеб. программа, метод. указания и контрол. задания для учащихся безотрыв. формы обучения специальности 2−40 01 01 «Программное обеспечение информационных технологий» / сост. М. А. Бельчик. — Мн.: МГВРК, 2008. — 56 с.

5. Котлинская Г. П., Галиновский О. И. Программирование на языке СИ: Справ. пособие. — Мн.: Выш. шк., 1991. — 156 с.

6. Основы программирования в среде С++ Builder: лаб. практикум по курсу «Основы алгоритмизации и программирования» для студ. 1−2-го курсов БГУИР. В 2 ч. Ч. 1 / Бусько В. Л. [и др.]. — Минск: БГУИР, 2007. — 70 с.

7. Романовская Л. М. Программирование в среде Си для ПЭВМ ЕС / Л. М. Романовская, Т. В. Рус, С. Г. Свитковский. — М.: Финансы и статистика, 1992. — 352 с.

8. Синицын, А. К. Алгоритмы вычислительной математики: учебно-метод. пособие по курсу «Основы алгоритмизации и программирования» / А. К. Синицын, А. А. Навроцкий. — Минск: БГУИР, 2007. — 80 с.

9. Шахгельдян, К.И. Объектно-ориентированное программирование: Учебное пособие / К. И. Шахгельдян; под ред. Л. И. Александровой. — [Электронное издание]. — Владивосток: ВГУЭС, 2000. — 191 с.

Показать весь текст
Заполнить форму текущей работой