Всё сдал! - помощь студентам онлайн Всё сдал! - помощь студентам онлайн

Реальная база готовых
студенческих работ

Узнайте стоимость индивидуальной работы!

Вы нашли то, что искали?

Вы нашли то, что искали?

Да, спасибо!

0%

Нет, пока не нашел

0%

Узнайте стоимость индивидуальной работы

это быстро и бесплатно

Получите скидку

Оформите заказ сейчас и получите скидку 100 руб.!


Процессы и IPC

Тип Реферат
Предмет Информатика и программирование
Просмотров
1544
Размер файла
31 б
Поделиться

Ознакомительный фрагмент работы:

Процессы и IPC

Сразу хочу огорчить программистов под Windows. К сожалению, некоторые из описанных ниже рецептов под Windows работать не будут. Я и сам долго скрежетал зубами, когда в ответ на переопределение STDOUT с помощью разветвляющего open в логи валились сообщения о том, что, мол, нет такой команды. Кого уж тут винить, не знаю, и искать не собираюсь. А советую всем, дабы не тратить свое драгоценное время, писать свои программы с расчетом на UNIX. Честно говоря, после всего, что я пережил, программируя под Windows, и узнав, что хостинг на IIS гораздо дороже (как очень редкий зверь что ли?) чем на UNIX-ах, я чуть из кресла не вывалился.

Процессы и с чем их едят

Давным-давно в одной далекой галактике жил-был DOS. И было у него всего-навсего 640 килов памяти, и мог выполнять он лишь только одну задачу. И появился грозный монстр Windows, который разделил процессорное время на части. Одну часть отвел он сонмищу процессов, а другую часть – сонмищу потоков. И перекликались они с помощью мьютексов и семафоров. А данные передавались где как. Была там и общая куча (heap), и пайпы кой где работали… В общем рассказывать дальше думаю не имеет смысла. Еще много чего можно написать - все это скучно и отвлекает от основных целей.

Так как все здесь описанное связанно с Perl, который проектировался с ориентировкой на UNIX-системы, все системные фишки, которые здесь будут рассмотрены, относятся именно к UNIX-системам. Конечно, реализация Perl для Windows скрывает кое-какие несоответствия, но далеко не все. Так что, сильно не огорчайтесь, если что-то не работает. Безвыходных ситуаций не бывает. Пишите в форум, а еще лучше побольше экспериментируйте – тогда все получится.

Итак, процесс – это программа, код которой выполняется независимо от других программ. Может быть это и не академическое определение, но ведь и наша задача не обозвать это правильно, а понять – как это работает и какая нам может быть от этого польза. Дабы не углубляться в системные тонкости, представим ситуацию на известных нам примерах.

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

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

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

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

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

fork;

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

На самом деле, оператор fork возвращает значение, которое используется для определения процесса. К примеру, выходит человек из-за угла, а ему кирпичом по голове. Очнулся, а в руке у него на бумажке написано – ты номер 1. Он встал и пошел дальше. Пойти то пошел, да на его месте опять же этот человек лежит. А у него в руке бумажка, на которой написано – ты номер 2. Этот человек поднялся, подумал, что сейчас вот зайду за другой угол, а там опять кирпичом по голове дадут, и пошел в другую сторону.

Так вот, вернемся к нашим баранам. Одному процессу достается значение, идентифицирующее порожденный процесс. То есть, дописываем в бумажку первого человека фразу типа "у второго номер 2". Это бывает необходимым, в случае если подразумевается взаимодействие с порожденным процессом. Порожденный процесс, получает от fork значение 0. Но возможны такие ошибочные ситуации, когда создать процесс не удалось. Возвращаясь к нашему примеру, человек заходит за угол и… Ничего не происходит. Человек думает, странно, здесь на меня должен упасть кирпич, видимо погода нелетная. Разворачивается и идет домой. Когда fork не возвращает значения (undef), значит породить процесс не удалось. Это, несомненно, ошибочная ситуация и ее необходимо обработать. В общем случае вызов fork должен выглядеть так

unless defined(fork) { print "обработайте ошибку, или вместо этого вызовите die" }

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

#!/usr/bin/perl –w

# fork.pl

die "Non-flying weather" unless defined(fork);

print "I'm number $$n";

В результате выполнения вы увидите что-то вроде

[root@avalon tests]# ./fork.pl

I'm number 6773

I'm number 6774

Так как процессы полностью дублируются, каждый процесс получает собственную копию данных, включая файловые дескрипторы и дескрипторы потоков ввода-вывода. Таким образом, оператор print в обоих процессах работает с одним и тем же дескриптором. Если кто не знает, встроенная переменная $$ содержит идентификатор текущего процесса Perl. Кстати, в качестве домашнего задания, можете добавить код, показывающий значение переменной $$ до выполнения fork. Тогда вы увидете, какой процесс является родительским и сделать вывод - в какой последовательности два дубликата начинают работать.

Да, чуть не забыл, важно завершать процесс оператором exit. Ну, думаю, хватит с вас бесполезной писанины. Пора заняться чем-нибудь более серьезным.

Фильтрация выходных данных

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

Погодите разминать пальцы. Сначала выпьем по кружке кофею, а я, в это время, обрисую ситуацию в целом. Что такое фильтр на выходные данные всем понятно? Ну, если кому не понятно, то опять же – представим. Программа что-то там выводит в STDOUT (стандартный поток вывода), а в это время какая-то другая программа тихо и незаметно ворует эти данные и делает с ними все что заблагорассудится. Реальный пример? Ну, самое первое, что пришло мне в голову – это замена всех URL на гиперссылки. Или в помощь рассеянному программисту, вечно забывающему о HTTP- заголовках, проверять наличие оных заголовков и добавлять их если нужно. На самом деле, все может быть гораздо сложнее. Например, вырезание ненормативной лексики (этакий невидимый цензор) из текста сообщения, отправляемого посредством WEB- интерфейса, перед тем, как оно будет передаваться на вход SENDMAIL. Ну и в таком духе.

В общем, первая наша цель, это каким-то образом подсунуть новый STDOUT, который мы можем прочитать, программе, вывод от которой мы будем фильтровать. Но тут возможны варианты. Например, может быть, мы хотим организовать вывод по типу транзакции: или программа выполняется до конца, и выводится все содержимое, или же, в случае ошибки нужно сбросить данные, а вывести, например, LOCATION на страницу обработки ошибок. То есть, все зависит от уровня контроля над фильтруемым выходным потоком. Что бы совсем стало понятно, о чем я здесь распинаюсь, давайте напишем простой примерчик, демонстрирующий "тупой" фильтр-нумератор строк.

#!/usr/bin/perl –w

# nfilter.pl

filter();

for ($i = 0; $i < 20; $i ++)

{ print "Output line $in"; }

sub filter

{

die "Cannot fork" unless defined($fpid = open(STDOUT,"|-"));

return if ($fpid != 0);

num = 0;

while (<STDIN>) { print "$num:t$_"; $num ++; }

exit;

}

Не вздумайте запускать. Что, уже запустили? Тогда жмите Ctrl+C. За то, теперь навсегда запомните – нужно закрывать дескрипторы (желательно все :). В чем же дело? Почему программа зависла? Все порожденные процессы являются процессами единой задачи. Потоки ввода вывода автоматически закрываются, когда завершается последний процесс. Конструкция open(STDOUT, "|-") неявно вызывает fork. Вспомните документацию по файловым операциям:

open(HANDLE, "| $cmd"); # направить информацию на вход программы

Так вот, здесь аналогичная ситуация, только в качестве программы здесь создается дочерний процесс. А так как в качестве дескриптора мы указываем STDOUT, то в настоящем процессе он переопределяется. Как и в случае с fork, относительно данных – дублируется их состояние на момент перед вызовом fork. Таким образом, в дочерний процесс попадает нормальный не переопределенный STDOUT. Замечу, что open с указанными аргументами в качестве результата возвращает те же самые значения, что и fork. Далее, программа определяет в каком она потоке – если не в порожденном ($fpid != 0), тогда возвращается и эмулирует вывод строк. Сам фильтр читает STDIN пока не закончатся данные. А данные закончатся, когда поток ввода будет закрыт (для родительского процесcа, это поток вывода). Родительский процесc уже завершил свою работу, а система ждет когда завершится последний процесс, что бы закрыть потоки. И так далее, и так далее. Чувствуете, где собака зарыта? После того, как вывод строк завершен, необходимо закрыть поток вывода, что бы фильтр, принимающий выходные данные через поток ввода вышел из цикла

while (<STDIN>) { print "$num:t$_"; $num ++; }

Вот так то, берем и правим

#!/usr/bin/perl –w

# nfilter.pl

filter();

for ($i = 0; $i < 20; $i ++)

{ print "Output linen"; }

close(STDOUT);

sub filter

{

die "Cannot fork" unless defined($fpid = open(STDOUT,"|-"));

return if ($fpid != 0);

num = 0;

while (<STDIN>) { print "$num:t$_"; $num ++; }

exit;

}

Ну это конечно, дюже примитивно. Но если нам нужно только лишь фильтровать, поток вывода, то сойдет. А вот если мы, например, пишем супер-систему обработки ошибок, то этого все-таки маловато. Представим, что этакий сторож фильтрует вывод и сразу отправляет его в настоящий STDOUT. А если возникла фатальная ошибка? Мы выводим сообщение об ошибке, но все это в догонку тому хламу, что уже был отправлен в STDOUT. Такая обработка ошибок, как говорится, "что мертвому припарка". Можно, конечно, накапливать вывод внутри фильтра и выводить только целиком. В случае чего, можно пришибить порожденный процесc с помощью оператора kill. Но увы, поток вывода уже переопределен безвозвратно.

Для решения этой проблемы мы должны кардинально изменить свое мировоззрение. Шучу, конечно. Достаточно вспомнить о таких полезных функциях как select и pipe. Функция select подменяет STDOUT новым дескриптором, а возвращает дескриптор потока вывода, который был актуален на момент до выполнения select, иначе говоря текущий STDOUT. Функция pipe связывает два дескриптора в режиме чтения-записи, то есть создает односторонний канал обмена данными. Отсюда и название – pipe.

Есть очень замечательное свойство систем UNIX - все потоки равны. Прям, коммунизм какой-то. Вот дедушка Ленин бы порадовался. А нам какая с этого польза? Ну как, мы, например, легко можем подсунуть функции select один из дескрипторов, связанных функцией pipe. Естественно, что будем подсовывать тот, который предназначен для записи, иначе я за последствия не ручаюсь. В общем такая незамысловатая программулина

#!/usr/bin/perl –w

# errfilter.pl

my ($fpid,$oldout);

pipe(FOR_READ,FOR_WRITE);

select((select(FOR_READ),$| = 1)[0]);

select((select(FOR_WRITE),$| = 1)[0]);

start_filter();

for ($i = 0; $i < 20; $i ++)

{ print "Output linen"; }

# Error("bug");

close(FOR_WRITE);

waitpid($fpid,0);

sub start_filter

{

die "Cannot fork" unless defined($fpid = fork);

unless ($fpid == 0)

{

close(FOR_READ);

$oldout = select(FOR_WRITE);

return;

}

close(FOR_WRITE);

my ($out,$num) = ("",0);

while(<FOR_READ>) { $out .= "$numt$_"; $num ++; }

close(FOR_READ);

print $out;

exit;

}

sub Error

{

my ($error_text) = @_;

select($oldout);

kill KILL => $fpid;

close(FOR_WRITE);

print "Error: $error_textn";

exit;

}

Ну что, налили очередную порцию кофе? Тогда приступим к разбору полетов. Первым делом, программа связывает два дескриптора FOR_READ и FOR_WRITE в канал с помощью pipe. При этом, FOR_READ получится только для чтения, а FOR_WRITE, соответственно, только для записи. Про следующие две строки скажу только что они отключают буфферизацию. Для нас это пока не важно, их можно вообще убрать. Далее вызывается функция start_filter(). Вот на нее нужно взглянуть со всей внимательностью.

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

Вернемся к функции start_filter() в той его части, где выполняется непосредственно фильтрация. Первым делом неиспользуемый в дочернем процессе конец канала закрывается. Далее, процесс в цикле считывает данные из канала и конкатенирует их в переменной $out. Ну далее должно быть все понятно. Запустите программу. Работает? По крайней мере должна.

Теперь уберите комментарии из строки, где вызывается функция Error("bug"). Запустите программу снова. Ну, каков результат? Этого мы добивались? (Правильный ответ да, если нет, то смотрите что вы там понаписали).

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

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

Что такое переменная

Переменные появились вместе с первыми языками программирования. Результат работы любой программы сводится к манипуляциям над какими-нибудь данными. Вы наверное уже знаете, что память - это последовательность ячеек, каждая из которых представляет собой числовое значение от 0 до 255 - 1 байт. Так как ячеек очень много, единственный вариант как то ориентироваться - это пронумеровать каждую ячейку. Так и есть - каждый байт оперативной памяти доступен процессору посредством порядкового номера ячейки - адреса.

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

С появлением первых языков программировани появилась очень полезная возможность ассоциировать с определенным адресом символьные имена. В отличии от адреса, имя переменной представляется некоторой лексемой, в достаточной мере отражающей содержимое конкретной ячейки памяти. Однако, имя это не все, что характеризует переменную. Так как процессор может работать с тремя типами данных (байт, слово и двойное слово), определение переменной в языках низкого и среднего уровней как правило сопровождается указанием типа переменной. Эти два параметра однозначно определяют расположение ячейки, и способ использования этой ячейки. Определим переменную типа байт (BYTE) с именем А. Естественно, что процессор, зная что переменная, находящаяся по такому адресу соответствует типу BYTE, при извлечении значения этой ячейки выберет такую команду, которая извлекает байт, а не слово или двойное слово.

В общем случае, переменная - это поименованная область памяти. В зависимости от языка, объявление переменной может сопровождаться указанием типа. Обычно, в языках высокого уровня указание типа не используется. Как правило, синтаксические различия между языками чаще всего проявляются именно в способах объявления переменных (C,C++ - конкретизация типа; perl - идентификатор структуры $,@ или %).

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

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

Что такое тип данных

Тип данных определяет, что из себя представляет значение и позволяет узнать, каким образом его можно(нужно) обработать. Типы подразделяются на две категории: базовые и пользовательские.

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

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

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

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

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

Теперь давайте разберемся со второй категорией типов данных - пользовательскими типами. Прилагательное "пользовательские" не совсем ясно отражает суть этой категории типов на данном этапе рассмотрения, правильнее было бы называть эти типы расширенными. Однако, это определение сразу же проясняется, когда мы начинаем говорить об этих типах как о наборах, состоящих из базовых типов. Проще всего уяснить суть на примерах. Для простоты мы будем рассматривать программу на языке perl, в котором тип единичного значения не существенен. Например, название улицы, номер дома и номер квартиры можно объединить в набор, представляющий собой новый тип значения - "адрес проживания". При этом, заметьте, что составные элементы нового типа представляют собой значения базовых типов: одного строкового и двух числовых. Однако, компилятор (или интерпретатор) не знает как обрабатывать новый тип "адрес проживания", он лишь знает как его хранить (так как знает способ хранения данных базовых типов). Программист должен реализовать механизм обработки самостоятельно.

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

Использование пользовательских типов данных является промежуточным этапом на пути к исследованию методологии объектно-ориентированного программирования. Этот этап относится к специфики модульного программирования. В качестве примера можно привести язык С, в котором введено понятие структур - возможности описания пользовательских типов, построенных на основе базовых. Структуры в C позволяют не только определять наборы, но также идентифицировать наборы и манипулировать ими на уровне единиц.

Следующим этапом эволюции в программирования было введение понятия класса данных. Методики объектно-ориентированного подхода в программировании очень хорошо просматриваются в языке C++. Считайте класс развитием структуры из C. Структуры позволяли только описывать данные, в то время как класс позволяет не только строить новые типы на основе базовых, но и определять методы обработки нового типа данных. Такое объединение данных и методов принято называть инкапсуляцией.


Нет нужной работы в каталоге?

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

Цены ниже, чем в агентствах и у конкурентов

Вы работаете с экспертами напрямую. Поэтому стоимость работ приятно вас удивит

Бесплатные доработки и консультации

Исполнитель внесет нужные правки в работу по вашему требованию без доплат. Корректировки в максимально короткие сроки

Гарантируем возврат

Если работа вас не устроит – мы вернем 100% суммы заказа

Техподдержка 7 дней в неделю

Наши менеджеры всегда на связи и оперативно решат любую проблему

Строгий отбор экспертов

К работе допускаются только проверенные специалисты с высшим образованием. Проверяем диплом на оценки «хорошо» и «отлично»

1 000 +
Новых работ ежедневно
computer

Требуются доработки?
Они включены в стоимость работы

Работы выполняют эксперты в своём деле. Они ценят свою репутацию, поэтому результат выполненной работы гарантирован

avatar
Математика
История
Экономика
icon
159599
рейтинг
icon
3275
работ сдано
icon
1404
отзывов
avatar
Математика
Физика
История
icon
156450
рейтинг
icon
6068
работ сдано
icon
2737
отзывов
avatar
Химия
Экономика
Биология
icon
105734
рейтинг
icon
2110
работ сдано
icon
1318
отзывов
avatar
Высшая математика
Информатика
Геодезия
icon
62710
рейтинг
icon
1046
работ сдано
icon
598
отзывов
Отзывы студентов о нашей работе
63 457 оценок star star star star star
среднее 4.9 из 5
Тгу им. Г. Р. Державина
Реферат сделан досрочно, преподавателю понравилось, я тоже в восторге. Спасибо Татьяне за ...
star star star star star
РЭУ им.Плеханово
Альберт хороший исполнитель, сделал реферат очень быстро, вечером заказала, утром уже все ...
star star star star star
ФЭК
Маринаааа, спасибо вам огромное! Вы профессионал своего дела! Рекомендую всем ✌🏽😎
star star star star star

Последние размещённые задания

Ежедневно эксперты готовы работать над 1000 заданиями. Контролируйте процесс написания работы в режиме онлайн

Подогнать готовую курсовую под СТО

Курсовая, не знаю

Срок сдачи к 7 дек.

только что
только что

Выполнить задания

Другое, Товароведение

Срок сдачи к 6 дек.

1 минуту назад

Архитектура и организация конфигурации памяти вычислительной системы

Лабораторная, Архитектура средств вычислительной техники

Срок сдачи к 12 дек.

1 минуту назад

Организации профилактики травматизма в спортивных секциях в общеобразовательной школе

Курсовая, профилактики травматизма, медицина

Срок сдачи к 5 дек.

2 минуты назад

краткая характеристика сбербанка анализ тарифов РКО

Отчет по практике, дистанционное банковское обслуживание

Срок сдачи к 5 дек.

2 минуты назад

Исследование методов получения случайных чисел с заданным законом распределения

Лабораторная, Моделирование, математика

Срок сдачи к 10 дек.

4 минуты назад

Проектирование заготовок, получаемых литьем в песчано-глинистые формы

Лабораторная, основы технологии машиностроения

Срок сдачи к 14 дек.

4 минуты назад

2504

Презентация, ММУ одна

Срок сдачи к 7 дек.

6 минут назад

выполнить 3 задачи

Контрольная, Сопротивление материалов

Срок сдачи к 11 дек.

6 минут назад

Вам необходимо выбрать модель медиастратегии

Другое, Медиапланирование, реклама, маркетинг

Срок сдачи к 7 дек.

7 минут назад

Ответить на задания

Решение задач, Цифровизация процессов управления, информатика, программирование

Срок сдачи к 20 дек.

7 минут назад
8 минут назад

Все на фото

Курсовая, Землеустройство

Срок сдачи к 12 дек.

9 минут назад

Разработка веб-информационной системы для автоматизации складских операций компании Hoff

Диплом, Логистические системы, логистика, информатика, программирование, теория автоматического управления

Срок сдачи к 1 мар.

10 минут назад
11 минут назад

перевод текста, выполнение упражнений

Перевод с ин. языка, Немецкий язык

Срок сдачи к 7 дек.

11 минут назад
planes planes
Закажи индивидуальную работу за 1 минуту!

Размещенные на сайт контрольные, курсовые и иные категории работ (далее — Работы) и их содержимое предназначены исключительно для ознакомления, без целей коммерческого использования. Все права в отношении Работ и их содержимого принадлежат их законным правообладателям. Любое их использование возможно лишь с согласия законных правообладателей. Администрация сайта не несет ответственности за возможный вред и/или убытки, возникшие в связи с использованием Работ и их содержимого.

«Всё сдал!» — безопасный онлайн-сервис с проверенными экспертами

Используя «Свежую базу РГСР», вы принимаете пользовательское соглашение
и политику обработки персональных данных
Сайт работает по московскому времени:

Вход
Регистрация или
Не нашли, что искали?

Заполните форму и узнайте цену на индивидуальную работу!

Файлы (при наличии)

    это быстро и бесплатно