Лабораторная работа 4. Контейнеры STL. Обработка исключений



Цель работы.

Цель работы – ознакомление с классами-контейнерами библиотеки STL, файловой системой и обработкой исключений.

Основные сведения

Контейнеры.

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

Контейнеры создаются в свободной памяти,  при этом  распределение памяти и сборка “мусора” выполняется автоматически. Классы-контейнеры подключается к программе с помощью одноименных заголовочных файлов.

Различают последовательные и ассоциативные классы- контейнеры. В данной работе используются только первые.

Среди последовательных - vector(вектор), list(список), deque(двусторонняя очередь) –  наиболее распространенным является vector. Отличительной особенностью vector, как и всех контейнеров, является возможность увеличения количества элементов, хранящихся в контейнере, в процессе выполнения программы c помощью методов соответствующего класса. На его основе можно конструировать динамические массивы элементов различных типов, в том числе и определенных пользователем.

Для добавления  в конец и удаления последнего элемента контейнера любого из трех рассматриваемых классов предназначены методы push_back() и pop_back(). Kpоме того, список и очередь (но не вектор) поддерживают операции вставки и удаления первого элемента контейнера push_front() и pop_front().

vector<double> vd; //Пустой контейнер

vd.push_back(45.56);

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

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

vector<int> v(20); // начальный размер контейнера – 20 элементов.

С этими 20 элементами  мы можем работать как с обычным статическим массивом, используя гораздо более эффективные операции индексации и  присваивания:

v[2]=3;

При этом в программе нужно следить за количеством элементов, которые необходимо поместить в контейнер,  и если их количество превышает в данном случае 20, переходить к push_back.

Размер контейнера может быть изменен при работе программы функцией resize(N).

vector <char> vc;

vc.resize(34); // Размер контейнера 34

vc[6]=’d’;

Аналогом  указателя в контейнерах является итератор. Он должен быть определен в программе.

vector <int> vv1;

vector<int> ::iterator iv1; //Итератор

Метод begin возвращает значение итератора – указателя на начало контейнера, метод end – на конец.

В библиотеке STL определено большое количество  т.н. алгоритмами (algorithm) – функций обработки элементов контейнеров: поиска(find), сортировки(sort) и т.п. При использовании алгоритмов могут использоваться   функциональные объекты [1]. Следует отметить, что алгоритмы не являются методами классов-контейнеров и могут быть использованы для работы с обычными массивами (см. замечание к листингу 1.1).

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

При использовании контейнеров надо помнить, что за увеличение возможностей, которые они предоставляют программисту, надо платить памятью и увеличением времени выполнения программы.

Работа с файлами   

Для работы с дисковыми файлами в языке С++ предусмотрен класс fstream и производные от него классы ifstream и ofstream. Для записи или считывания данных надо объявить объект соответствующего класса и связать его с файлом.

Например,

ifstream fin ( имяфайла, режим_чтения);

ofstream fout(( имяфайла, режим_записи);

В классе fstream для файловых объектов определены операции вставки и извлечения, так что для стандартных типов и строкового типа string можно применять привычную запись типа fin>> …, fout<<…. Для пользовательских типов операции надо переопределять (см. пример программы ниже).

 Двухаргументные методы read и write позволяют считывать/записывать в файл блоки двоичных данных. Количество байт в блоке является аргументом этих методов. Считываются и записываются символьные массивы типа char*; числовые типы следует преобразовывать, например, операцией reinterpret_cast<char*>. Операция преобразования позволяет сохранять в файле объект целиком, а не по компонентам.

Обработка исключений

Под исключением понимается некоторая ситуация, возникающая при выполнении программы, вследствие появления которой нормальное продолжение программы невозможно. Дальнейшее выполнение программы определяется программистом на этапе проектирования и носит название обработки исключения. Прерывание программы пользователем или от аппаратуры ( нажатие клавиш Ctrl-Break, сигнал таймера) как исключения не рассматриваются.

В С++ введен специальный механизм обработки исключений. Он организуется при помощи трех ключевых слов: try, catch и trow.

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

Схема размещения такова:

try { …

throw выражение1;

….

throw выражение2;

…..

}

catch (тип арг1)

{ ….}

catch (тип арг2)

{ ….}

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

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

Примеры организации исключений.

void main()

{

try {……..

…. throw 1;

……..

…. throw ‘a’;

}//try

catch (int){…….}

catch (char) {…..}

}//main

Операторы throw могут быть включены в функцию, а вызов ее помещен в блок try

void MyFunc(){

……..

if(…)throw 1;

 

……..}//MyFunc

void main()

{try

{ MyFunc(); ……

}//try

catch(int){……}

}//main

Наконец, блоки try и catch могут быть включены в функцию.

Рекомендуется создавать пользовательские классы исключений.

Например,

class ReadError {

 public: ReadError () {cout << “Error Read”;}

};

class WritedError {

 public: WriteError () {cout << “Error Write”;}

};

void main ()

{ try{

 ifstream in(“имя”);

if(!in) throw ReadError ();

….

ofsteam out (“имя”);

if(!out) throw WriteError();

….

}//try

catch(ReadError){…}

catch(WriteError){….}

}//main

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

Ниже приводится пример программы с использование контейнера типа vector c объектами класса   MyRecord.  

листинг 4.1

#include "stdafx.h"

#include <iostream>

#include <fstream>

#include <vector>

#include <string>

#include <ctype.h>

#include <algorithm>

using namespace std;

class MyRecord; // Объявление класса

typedef vector <MyRecord> Base; // Переименование типа - необязательно

vector<MyRecord>::iterator index ; //Определение итератора index

class MyRecord{

string Name;

int age;

public:

/* Здесь можно включить проверку правильности ввода данных,

 например, в name не должны вводиться цифры, возраст не может превышать 100 и т.п.*/

void InputRecord()

  {  

       string name;

           int len;

           cout<<"Input Name & Age"<<endl;

       cin>>name;

       len=name.length();

         for(int i=0; i<len; i++)

        if(isdigit(name[i])) throw 1;//isdigit в <сtype.h>

       Name=name;

   cin>>age;

    }

void ShowRecord() const { cout<<Name<<" "<<age<<endl;}

int GetAge()const {return age;}

 string GetName()const {return Name;}

/* На всякий случай - перегрузка вставки и извлечения для файловых

объектов и класса MyRecord*/

friend ifstream& operator >> (ifstream& s, MyRecord& obj)

{ s>>obj.Name>>obj.age; return s;}

friend ofstream& operator << (ofstream& s, MyRecord& obj)

{ s<<obj.Name<<endl<<obj.age<<endl; return s;}

/*Перегрузка операции < для применения алгоритма сортировки из библиотеки

algorithm; сортировка ведется по полю Name*/

bool operator<( MyRecord b)

{

  if(Name<b.Name) return true;

   return false;

}

 

};

    

class MyBase{

Base bs;

MyRecord mr;

public:

//ввод элементов в контейнер

void InputBase()

char flag=true;

while (flag)

{

try

{ mr.InputRecord();

bs.push_back(mr);

  flag=false;

}//try

catch(int) { cout<<"Once more Name"<<endl; }

}

 

}

void ShowBase()

{ int n=bs.size();

for (int i=0; i<n; i++)

 bs[i].ShowRecord();

}

//Перегрузка индексации для MyBase 

MyRecord& operator [](int i)

{return bs[i]; }

//Очистка контейнера

void ClearBase()

{bs.clear(); }

//Вычисление среднего значения элементов age в контейнере

int AverageAge()

{

int n=bs.size();

 int buf=0;

 for(index=bs.begin(); index!=bs.end(); index++)

 buf=buf + (*index).GetAge();

 buf=buf/n;

 return buf;

}

//Сортировка

void SortBase()

{ sort(bs.begin(),bs.end());}

//Запись в файл содержимого контейнера

void InFile()

{//Здесь включить try на открытие файла

    fstream out("c:\\Base.txt",ios::out);

int n=bs.size();

for (int i=0; i<n; i++)

out<<bs[i].GetAge()<<" "<<bs[i].GetName();

}

}; 

 

 

int main()

{

MyBase mb;

mb.InputBase();

mb.ShowBase();

mb.SortBase();

mb.InFile();

mb.ClearBase();

mb.ShowBase();

return 0;

}

Замечания

1. Класс  Base служит фасадом. В нем инкапсулированы все методы работы с контейнером, благодаря чему main выглядит очень незатейливо.

2.  Обратите внимание, что методы ShowBase и AverageAge выполнены по-разному: один с использованием индексации, второй с применением итераторов. В данном случае ( для класса vector) оба метода можно сделать по одному типу – или с индексацией или с итераторами. Но итераторы работают и для других последовательных контейнеров – list и deque, а индексация определена только для vector.

2. В приведенной программе невозможно ввести в контейнер больше одной записи. Исправить это легко – достаточно в main запустить InputBase в цикле. Но делать так не следует, так как этим мы усложним работу клиента. Посмотрите пример из 2-й работы, где массив элементов создается в отдельном классе. Здесь такой класс уже есть и в нем достаточно организовать InputBase  такую, что можно было бы добавлять в контейнер несколько элементов без предварительного создания соответствующего массива. Однако, вам придется использовать resize(N) после создания контейнера, вводя значение N по запросу, и комбинировать присваивание и push_back .

 

Варианты задания

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

Предусмотреть обработку не менее 2-х исключительных ситуаций, возникающих, например, при вводе данных с консоли и работе с файлом; обработчики данных должны указывать на место и причину возникновения ситуации и предлагать способ ее преодоления.

Во всех нижеследующих вариантах написать программу по типу приведенного примера, в основе которой лежат следующие классы:

 

1. Класс “Студент (Student)” с полями: ФИО студента, номер группы, успеваемость (progress-массив из 3-х элементов – количество пятерок, четверок, троек. Сортировать записи по ФИО; вывести  фамилии и группы студентов, средний балл больше задаваемой цифры.

 

2. Класс “Расписание_полетов (FlightShedule)”  с полями: дата вылета, пункт назначения, номер рейса, тип самолета. Сортировать записи   по дате; вывести номера рейсов и типов самолетов, вылетающих в задаваемый пункт назначения в задаваемую дату.

 

3. Класс  «Поезд (Train)» с полями: пункт назначения, номер поезда, время отправления. Сортировать записи по пункту назначения; вывести  номера поездов и пунктов назначения, отправляющихся после задаваемого времени.

 

4. Класс  “ Записная книжка (Notebook)”  с полями: ФИО, номер телефона, дата рождения. Сортировать записи по ФИО; вывести ФИО и номер телефона человека с задаваемой датой рождения.

 

5. Класс “Знаки зодиака (ZodiacSigns)” с полями: ФИО, знак зодиака, день рождения, краткая характеристика знака. Сортировать записи по дате рождения; вывести дату дня рождения и знак зодиака человека, фамилия которого вводится с клавиатуры.

 

6. Класс “Цена(PriceList)” с полями: название товара, название магазина, стоимость товара в руб. Сортировать записи по названию товаров; вывести информацию о заданном товаре с задаваемой  максимальной ценой, которую готов платить покупатель.

 

7. Класс “Счет(Invoice)” с полями: расчетный счет(6 знаков) плательщика, расчетный счет покупателя, перечисляемая сумма, дата. Сортировать записи по расчетным счетам плательщиков; вывести информацию о сумме, снятой с задаваемого расчетного счета плательщика до задаваемой  даты.

 

8. Класс “Университет(University)” с полями: название, город,   перечень специальностей ( до 5), с пропускным баллом по ЕГЭ каждая. Сортировать  записи по названию города; вывести информацию о баллах ЕГЭ по задаваемой специальности в разных университетах.

 

9. Класс “Общежитие (Hostel)” с полями: ФИО студента, номер группы, номер комнаты. Сортировать записи по номеру комнат; вывести информацию о студентах группы, номер которой вводится с клавиатуры.

 

10. Класс “Вычислительный центр(ComputingCenter)” с полями: номер лаборатории, тип процессора, величину ОЗУ, емкость диска,   тип монитора. Сортировать  записи по номеру лаборатории; вывести в файл и на дисплей информацию о компьютерах, величина ОЗУ которого вводится с клавиатуры.

 

11. Класс “Работник(Employee)” с полями: ФИО, должность, год поступления на работу. вывод в файл и на дисплей информации о работниках, чей стаж работы превышает значение, введенное с клавиатуры.

 

12.  Класс «Библиотека(Library)» с полями: ФИО автора книги, название, год изда­ния, количество экземпляров данной книги в библиотеке. Сортировать записи по автору;

вывести  сведения  о всех книгах  автора, начиная с заданного года издания, ФИО которого вводится с клавиатуры.

 

13. Класс «Квартира(Flat)» с полями, описывающими квартиру, предназначенную к продаже: площадь, количество комнат, этаж, район. Сортировать записи и выводить по заявке на покупку, в которой указана только площадь, информацию по имеющимся квартирам, в которых площадь отличается от заявленной не более, чем на 10%.

 

14. Класс «Выборы(Elections)» с полями: ФИО кандидата, дата рождения, место работы, рейтинг предварительных опросов;

вывод  первых 5 наиболее рейтинговых кандидатов.

 

15. Класс «Каталог(Catalogue)» с полями: имя файла, дата создания, количество обращений к файлу;

вывод перечня файлов с наибольшим количеством обращений.

 

16. Класс «Город(Town)» с полями: название, население, средний доход жителя, средняя цена кв.м. жилья, наличие зеленых зон и т.п. (посмотрите в Сети). Вывод пятерки наиболее комфортных для проживания городов.

 

17. Определить класс «Кинотеатр» с полями «Фильм», «Количество мест», «Количество посетителей», «Длительность фильма», «Стоимость билета» и «Время сеанса»;

вывод статистики посещения кинотеатра по времени суток и по наименованию фильма.

 

18. Определить класс «Сервер» с полями «Пользователь», «Домашняя страница», «Загруженность трафика», «Оплата за услуги». Предусмотреть операции по добавлению новых пользователей, созданию и удалению домашних страниц для пользователей, а так же оплаты за услуги пользования сервером для конкретного пользователя с учетом загруженности трафика и размера домашней страницы.

19. Определить класс «Магазин» с полями «Товар», «Продавец», «Зарплата продавца», «Рейтинг продаж», предусмотреть возможность удаления/добавления товаров, продавцов, а так же создать функцию зависимости зарплаты продавцов от рейтинга продаж.

 

20.  Определить класс «Штаб» с полями «Сотрудник», «Должность», «Зарплата», «Задания сотрудника». Функции: изменения контингента сотрудников, назначения сотруднику задания, установления зарплаты в зависимости от количества заданий и должности.

 

 

Контрольные вопросы

 

1. Что представляет из себя контейнер? Покажите контейнер в своей программе.

2. В процессе отладки программы появилась необходимость увеличить массивы, объявленные ниже, на 4 элемента. Можно ли это сделать в первом и во втором случаях, не изменяя константу 10?

int *mas1=new int[10]; // 1

vector <int> mas2(10); //2

3. Если работа с массивами, объявленными выше, заканчивается, то в каком случае обязательно использование оператора delete?

4. Если вы хотя бы приблизительно знаете размер динамического массива в программе, то является ли удачным объявление его как нулевого вектора  и неиспользование resize() и почему?

vector <MyClass> my;

5. Что представляет из себя итератор? Что возвращают begin() и end()?

 6. Можно ли обрабатывать исключительные ситуации, не используя try, throw, catch, и если да, то зачем нужны последние?

7. Какие сообщения и в какой последовательности будут выведены на монитор при а=1 и a=0 и почему?

class Alpha {

public:

Alpha(){cout<<"Constructor A"<<endl;}

~Alpha(){cout<<"Destructor A"<<endl;}

};

 

void myfunc() {

try {

Alpha alf; 

      int a;

      cin>>a;

      if ( a) throw 1;

     cout << “End of function”;

}

 catch(int) {cout<<"HandleIn"<<endl;}

cout<<"Continue"<<endl;

 }//myfunc

 

int main()

{ myfunc();

return 0;

}

 

8. Разберитесь в приведенном фрагменте программы и ответьте, почему в иерархии исключений единственный обработчик запускает нужную функцию ErrProcess.

//Базовый класс обработки ошибок

class MathError {

virtual void ErrProcess() {};

}; // MathError

//Класс ошибок переполнения

class Overflow:public MathError {

void ErrProcess (){/*…*/};

}; // Overflow

//класс ошибок деления на 0

class ZeroDivide: public MathError {

void ErrProcess() {/*…*/};

}; // ZeroDivide

 

/* …………*/

try {

/* В точках возникновения ошибок записываются операторы

if(…) throw Overflow vr;

  /*…*/

if(…) throw ZeroDivide vr;…

*/

}

// единственный обработчик для всех типов исключений

catch (MathError& vr)

{vr.ErrProcess();

}


 

Лабораторная работа 5. Классы, объекты, наследование  в С#

Цель работы

Ознакомление с основами программирования на С#.

Основные сведения

Известной монографией по программированию на С#, включая материал по созданию графических интерфейсов, является [5]. В [6] кратко рассмотрены основные вопросы.

Приведем программу, реализующую класс комплексных чисел аналогичную 1.1; шаблон программы выполнен мастером Visial Studio 2012.

Листинг 5.1

using System

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

 

namespace ConsoleApplication1

{

class Complex

{ //Поля

   public double real;

   public double imag;

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

      //Пустой

   public Complex() { }

     //С параметрами

   public Complex(double _r, double _im) { real = _r; imag = _im; }

           

   // Методы

   //Ввод числа

   public void SetComplex()

   {

       string re, im;

      Console.WriteLine("Действительная часть ? ");

       re = Console.ReadLine();

       this.real=Convert.ToDouble(re);

       Console.WriteLine("Мнимая часть ? ");

       im = Console.ReadLine();

       this.imag = Convert.ToDouble(im);

                      

   } // Вывод числа

   public void ShowComplex()

   {

       Console.WriteLine(real + " +i" + imag);

   }

   //Перегрузка операций

   //cложения  

   public static Complex operator +(Complex t, Complex s)

   {

       Complex tmp = new Complex();

       tmp.real = s.real + t.real;

       tmp.imag = s.imag + t.imag;

       return tmp;

   }

   //умножения

   public static Complex operator *(Complex t, Complex s)

   {

       Complex tmp = new Complex();

       tmp.real = s.real * t.real - s.imag * t.imag;

       tmp.imag = s.imag * t.real + s.real * t.imag;

       return tmp;

   }

} //Complex

  

class Program

{

   static void Main(string[] args)

   {

     Complex cm1=new Complex();

     Complex cm2=new Complex();

     Complex cm3 =new Complex();

 Console.WriteLine ("1-е число ");

 cm1.SetComplex();

 Console.WriteLine ("2-е число ");

 cm2.SetComplex();

 Console.WriteLine ("Сумма:");

 cm3=cm1+cm2;

 cm3.ShowComplex();

 Console.WriteLine ("Произведение:");

 cm3=cm1*cm2;

 cm3.ShowComplex();

//Использование конструктора с параметрами

 Complex cm4=new Complex (34.7, 21.8);

 Console.WriteLine ("Массив из 2-х чисел");

Complex[] cm5=new Complex[2];

for (int i = 0; i < 2; i++)

{

     cm5[i] = new Complex();

     cm5[i].SetComplex();

}

}

}

}

Не касаясь принципиальных различий между выполнением программ на стандартном С++ и CLR Visual Studio .Net, посмотрим на различия между листингами.

Определение класса Complex практически не отличается от определения такого же класса на языке С++ - модификатор public не имеет заключительного символа ‘:’ ; после определения класса нет символа ‘;’ . Вместе с тем, программа существенно отличается от C++.

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

Существенное различие существует в концепциях типов в С# и в С++. Прежде всего, типы данных в С# подразделяются на типы – значения (value types) и ссылочные типы(reference types). Величины ссылочного типа хранятся в динамической памяти, а переменные типов-значений в памяти, управляемой компилятором. В частности, объекты классов относятся к ссылочным типам и создаются только в динамической памяти с помощью оператора new. Освобождение памяти от объектов ссылочного типа производится автоматически.

 Главная функция является компонентом класса, а не глобальной функцией, как в С++ - глобальных компонент в С# нет. Главная функция - статический компонент, что позволяет вызывать ее без создания объекта соответствующего класса.

Все классы системные и пользовательские являются наследниками класса System.Object (object), однако упоминание его в программе как базового необязательно.

При перегрузка операций количество операндов должено совпадать с количеством операндов стандартной операции. Перегруженная операция является статической.

Механизм наследования в С# работает так же, как и в С++. Виртуальные функции в производных классах сопровождаются словом override.

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

 

namespace Гараж

{

class Vehicle{

 protected int price;//цена

protected int year; //год выпуска

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

public virtual void setVehicle(){}

public virtual void getVehicle(){}

       

}

class Lorry: Vehicle{

int capacity;

override public void setVehicle(){

Console.WriteLine("setLorry");

price=40000; year=5;capacity=600;

}

override public void getVehicle(){

Console.WriteLine("Lorry" +price +" "+year+" "+capacity);}

 }

class Car: Vehicle{

int speed;

//То же для авто

override public void setVehicle(){

    Console.WriteLine("setCar");

   price=10000; year=2;speed=180;}

override public void getVehicle(){

    Console.WriteLine("Car "+price+" "+year+" "+speed);}

}

class Garage

{

public static int n=2;

//Массивы ссылок на производные классы 

public Lorry[] lor=new Lorry[n];

public Car[] car= new Car[n];

//Ссылка на базовый класс

public Vehicle vec=new Vehicle();

public Garage()

{

//Инициализация ссылок на производные классы

for (int i=0; i<n; i++)

{ car[i]=new Car();

lor[i]= new Lorry();

}

}

    

// Ввод и вывод данных для машин с вызовом виртуальных функций

public void setVehicle(){

      for(int i=0; i<n; i++)

      { vec=car[i]; //Автомобили

     vec.setVehicle();

     vec=lor[i]; //Грузовики

     vec.setVehicle();

     }

 }

public void getVehicle(){

 for(int i=0; i<n; i++)

      { vec=car[i];

      vec.getVehicle();

vec=lor[i];

     vec.getVehicle();

      }

 }

    

}

 

class Program

{

   static void Main(string[] args)

   { Garage g= new Garage();

    g.setVehicle();

          g.getVehicle();

 

   }

}

}// namespace

 

В качестве задания выбирается соответствующий вариант 2-й работы.

Контрольные вопросы

1. Как построена система типов в С#?

2. В чем заключается разница между массивом в С++ и в С#(кроме объявления)?

  1. В какой строке нижеследующей программы на С# компилятор обнаружит ошибку и почему? Сохранится ли эта ошибка в том же коде, если он будет откомпилирован на С++?

class A {public int x;}

/* …...*/

A a1;

a1.x=10;

4. Почему функция Main в С# должна быть статической?

 

 

Требования к отчету

 

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

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

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

 Кроме отношений наследования и агрегации при составлении диаграммы следует применять отношение зависимости(использования): класс А вызывает некоторый метод класса B или класс А имеет метод, в параметрах которого используется класс B. Например,

class A {

 

……..

int mymethod (B arg) { …..}

 

};

 

 

 

 

A
B
 


Дата добавления: 2018-04-15; просмотров: 1451; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!