Министерство общего и профессионального образования
Российской Федерации
Московский физико-технический институт
Кафедра вычислительной математики
«Утверждаю»
Проректор института
Методические указания по курсу:
Вычислительная техника и программирование
ВВЕДЕНИЕ В ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ НА ЯЗЫКЕ С++
А.С.Холодов
П.Н.Коротин
Москва 1997
УДК 681.32
Методические указания к практикуму по курсу: Вычислительная техника и программирование. Введение в объектно-ориентированное программирование на языке С++/ МФТИ. М., 1997. 76 с.
В методические указания включены описания основных особенностей языка программирования С++. Даются основные понятия, присущие С++, такие как инкапсуляция, полиморфизм, наследование, перегрузка операторов, дружественные функции. Описываются методы работы с потоками данных, классами, особенности простого и множественного, открытого, закрытого и виртуального наследования.
© Московский физико-технический институт, 1997
Язык программирования С был разработан в фирме Bell Laboratories Деннисом Ритчи (Dennis M. Ritchie). Первоначально он был реализован для операционной системы UNIX. В настоящее время С является одним из наиболее распространенных языков программирования и реализован для большинства ЭВМ и операционных систем. Одним из преимуществ языка С является то, что редко возникает необходимость в подпрограммах на языке ассемблера. Иногда С даже называют наиболее точной аппроксимацией мобильного языка ассемблера, доступного в настоящее время. В последнее время появилось достаточно книг, довольно подробно и широко обсуждающих особенности языка программирования С. Однако, как впрочем и большинство языков программирования, С постоянно развивается, обогащаясь новыми подходами и современными идеями. Программистам уже трудно ужиться в рамках языка С, что, видимо, и привело к появлению нового языка, надмножества языка С, называемого С++.
В отличие от остальных "собратьев" С++ не является диалектом языка С или вариацией на его тему. По существу, это новый язык программирования, основанный в значительной мере на языке С. С++, разработанный в начале 80-х годов также сотрудником Bell Laboratories Бьярном Страустрапом (Bjarne Stroustrup), представляет собой совместимое снизу вверх расширение языка программирования С, поддерживающее современную методологию построения больших программных комплексов.
Основным понятием С++ является класс. Классы обеспечивают сокрытие данных, их гарантированную инициализацию, неявное преобразование типов для типов, определенных пользователем, механизмы перегрузки операций, контролируемое пользователем управление памятью. Такой метод построения программ часто называют абстракцией данных, а программирование с применением таких объектов - объектно-ориентированным программированием. В последнее время все большую популярность приобретает мнение, что в 90-е годы практика разработки программ в основном будет связана с идеями объектно-ориентированного программирования, подобно тому, как это происходило в 80-е годы со структурным программированием.
Язык программирования С++ ориентирован в первую очередь на профессиональных программистов, для начинающих его использование может быть затруднительным.
В предлагаемой Вашему вниманию небольшой разработке основное внимание уделено описанию возможностей языка С++. Сведения о С приводятся, как правило, фрагментарно и связаны с прямым расширением языка. За более детальным изложением языка С следует обратиться к бо-лее толстым руководствам, таким, как, например:
Б.В.Керниган, Д.Ритчи, А.Фьюэр. Язык программирования Си. М.: Финансы и статистика, 1985;
Я. Белецкий. Энциклопедия языка Си. М.: Мир, 1992
или практически любому руководству по ОС UNIX.
Очень краткое (и потому затруднительное для первого чтения) руководство для имеющих практику работы с этим языком представляют
М.И.Болски. Язык программирования Си. Справочник. М.: Радио и связь, 1988;
Дерк Луис. С и С++. Справочник. М.: Бином, 1997.
В последнее время вышло очень много толстых книг по С++. Более полное изложение С++ можно найти, например, в
B.Stroustrup. The C++ Programming Language. Addison-Wesley, Reading, Mass., 1986;
I.Pohl. C++ for programmers. The Benjamin / Cummins Publishing Company, Inc. Redwood City, 1989;
Том Сван. Освоение Borland® C++ 5. Киев: Диалектика, 1996;
Тэд Фейсон. Объектно-ориентированное программирование на Borland® C++ 4.5. Киев: Диалектика, 1996;
Стивен Поттс, Тимоти С. Монк. Borland® C++ в примерах. Минск: Попури, 1996.
Подробнее в этой брошюре рассматриваются основные идеи, связанные с объектно-ориентированным программированием.
Прямые расширения
Прямые расширения языка С были введены в язык С++ с целью создания условий, затрудняющих появление наиболее типичных ошибок. Эти расширения включают в себя: изменения в механизме контроля и приведения типов аргументов функций, введение функций, представляющих собой открытые подстановки (inline), и литеральных констант, введение нового механизма передачи аргументов функциям с переменным числом аргументов и семантически новой возможности описания переменных.
Описания и константы
Любое имя, появляющееся в программе, вводится описанием, которое задает его тип и, возможно, начальное значение. В С описания переменных могут располагаться только в начале блока до первого исполнимого оператора.
|
int i=1; |
/* описание целой переменной i и присваивание ей начального значения 1 */ |
|
|
float a; |
// вещественная переменная a |
|
|
char s='a', str[10]; |
// символ и массив символов |
|
|
char* name="Mike"; |
// указатель на символьную строку |
|
|
struct complex { float re, im; }; |
/* описание структуры комплексного числа */ |
|
|
extern complex sqrt() |
/* внешняя функция, возвращающая в качестве значения комплексное число */ |
Здесь, наряду с операторами, помещены комментарии. Два символа наклонной черты выделяют текст, являющийся комментарием. Концом комментария служит конец строки. Символы /* и */ выделяют комментарии, как это принято в С.
Из примеров видно, что описание не есть только лишь простое определение имени. Большинство описаний определяют также сущность вводимого объекта.
В языке С++ описания могут размещаться в любом месте блока нарав-не с другими операторами. В этом случае область действия описанного имени лежит между оператором описания и фигурной скобкой, обозна-чающей конец блока, внутри которого это описание помещено. Это позволяет описывать рабочие переменные непосредственно в том месте, где они используются. Область действия описания называется областью видимости.
Например, описание функции, выполняющей заполнение элементов массива нулями, могло бы выглядеть так:
#define SIZE 6
float a[SIZE];
void clear()
{
for(int i=0; i<SIZE; i++) a[i]=0.;
}
Область действия переменной i в данном случае начинается с операто-ра for и заканчивается закрывающей фигурной скобкой (дело в том, что группа операторов инициализации в цикле for относится компилятором к операторам, предшествующим циклу). Имена, описанные внутри блока, называют локальными именами.
Недостатком данного программного фрагмента является то, что подстановка значения символьной константы SIZE выполняется препроцессором, и поэтому информация о типе и даже имени литеральной константы от других инструментальных средств таких, как, например, отладчик, оказывается сокрытой. В языке С++ преодолеть этот недостаток возможно, явно задав описание литеральной константы в виде
const int SIZE=6; ,
а не ее подстановку.
Для имен, описанных не в функции и не в классе, область видимости простирается от момента описания до конца файла, поэтому такие имена часто называют глобальными. Описание в блоке имени может приводить к сокрытию такого же глобального имени или имени, описанного во внешнем блоке, охватывающем данный. Это означает, что в блоке можно переопределять имя для ссылки на другой объект. После выхода из блока такое имя вновь обретет свое прежнее значение. Скрытым глобальным именем можно воспользоваться, применяя операцию :: - расширения области видимости
int n=10;// глобальное n
void clear(int* b)
{
int n;// локальное n; глобальное имя n скрыто
for( n=0; n<::n; n++ ) b[n]=0;
}
int* ptr=&n;// присваивание указателю адреса глобального n
Возможности использовать скрытое локальное имя нет.
Имена параметров функции считаются описанными в самом внешнем блоке, поэтому
void f(int x)
{
int x;
}
содержит ошибку, т.к. имя x определено дважды в одной и той же области видимости.
Время жизни
Как правило, объект создается и, возможно, инициализируется, когда встречается его описание, и уничтожается, когда имя объекта выходит за область видимости (такие переменные называют автоматическими). Объекты с глобальными именами и локальные объекты, при описании которых используется слово static, являются статическими, они создаются и инициализируются только один раз и существуют до завершения программы. Если инициализация статической (static) переменной явно не производится, то неявно она инициализируется нулем.
Время жизни объектов, порождаемых программистом в динамической памяти с помощью операторов new, определяется программистом. Уничтожаются такие объекты оператором delete.
Идентификаторы
Имя состоит из последовательности букв и цифр, причем первый символ - буква. Буквы верхнего и нижнего регистров считаются различными. Буквой считается также символ подчерка (_). В качестве имен не могут использоваться ключевые слова языка.
Не желательно использовать при написании программы имена, незначительно отличающиеся друг от друга, т.к. это часто приводит к ошибкам. Имена, начинающиеся с подчерка, как правило, используются для специальных средств среды выполнения, поэтому без необходимости использовать такие имена также не нужно.
При компиляции программы транслятор ищет наибольшую последовательность символов, которая может быть именем. Поэтому var10 - это одно имя, а не имя var, за которым следует число 10. Так же, как и elseif, - это одно имя, а не ключевое слово else, после которого стоит ключевое слово if.
Типы
Каждый идентификатор в программе имеет ассоциированный с ним тип. Необходимость этого связана с тем, что следует знать, какие опера-ции возможно применять к объекту, на который имя ссылается, как эти операции трактуются.
В набор основных типов в С входят:
|
char |
- значения, на которое отводится один байт для представления символа из множества знаков, имеющихся в используемой системе; |
|
|
int |
- целые значения. Допустимый диапазон зависит от конкретной системы (обычно от 32768 до +32767); |
|
|
float |
- вещественные значения, которые содержат как целую, так и дробную часть. Допустимый диапазон и число значащих цифр зависят от конкретной реализации; |
|
|
double |
- вещественные значения с плавающей точкой с удвоенной точностью (как правило, с удвоенным числом значащих цифр по сравнению с float). |
Существуют три модификатора, использующиеся для модификации основных типов:
short- для уменьшения размера памяти, отводимой под тип;
long- для увеличения размера отводимой под тип памяти;
unsigned- для представления без знаковых величин.
Например, для представления целых чисел различных размеров используются
char
short int
int
long int
Для представления без знаковых целых, логических значений, битовых массивов используются:
unsigned char
unsigned short int
unsigned int
unsigned long int
В комбинациях из нескольких слов спецификатор int можно опускать, что не меняет смысла:
const a = 1;
static x;
здесь все описания вводят объекты типа int.
Целый тип char наиболее удобен для хранения и обработки символов, обычно это 8-битовый байт. В зависимости от реализации char может быть как знаковым, так беззнаковым целым. Тип unsigned char, конечно, всегда беззнаковый, и при его использовании получаются более переносимые программы, но из-за применения его вместо просто char могут возникнуть значительные потери в эффективности.
Основные типы можно свободно сочетать в операторе присвоения и выражениях. Везде, где это возможно, значения неявно преобразуются так, чтобы информация не терялась. Существуют случаи, когда информация при неявных преобразованиях теряется или искажается.
Так, использование unsigned в качестве гарантии того, что целое значение положительно, опрометчиво из-за правил неявного преобразования. Например, вполне возможно
unsigned surprise = -1;