Содержание
Лекция № 1. Основные понятия языка C++. Переменные, константы. Резервирование памяти, инициализация, типы и их значения, символы. Выражения. Операторы. операции. Линейные программы. Операторы отношений. логические операторы. оператор ветвления. 3
Процесс создания программы. 3
Переменные и константы. 4
Оператор ветвления if. 5
Лекция № 2. Циклы. Счётчики. Указатели. память. размещение объектов в области динамической памяти. ссылки. Адреса. передача аргументов функции как ссылок. возвращение нескольких значений. 7
Циклы. 7
Оператор switch. 8
Указатели. 9
Лекция № 3. Функции. Объявление и определение функции. выполнение функции. Локальные и глобальные переменные. Аргументы функции — фактические и формальные. Перегрузка функций. возвращаемые значения. Массивы. 11
Функции. 11
Использование функций. 11
Макрофункции.. 12
Перегрузка функций. 13
Возврат более одного результата. 13
Лекция № 4. Массивы. Элементы массива. инициализация массива. объявление массива. Динамические и статические массивы. Многомерные массивы. Строковые. 15
Массивы. 15
Лекция № 5. Структуры. Доступ к элементам структуры. Инициализация. Выделение памяти. работа с динамическими типами данных . работа со стеком, очередью, деком, деревом. (Самостоятельное изучение) 17
Создание новых типов. 17
Шаблон структуры.. 17
Структурные переменные. 17
Инициализация структуры.. 18
Массив структур. 19
Передача структуры в функцию.. 20
Вложенные структуры.. 20
Лекция № 6. Базовые классы. Классы и члены. Получение доступа к членам класса. Ограничение доступа к членам класса. определение методов класса. Конструкторы и деструкторы. Вложенные классы. структуры. 22
Классы. 22
Доступ к членам класса. 22
Лекция № 7. Перегрузка функций-членов. Инициализация объектов. Перегрузка операторов. Операторы преобразований. Наследование. 24
Дополнительные возможности использования функций. 24
Функции — друзья. 25
Перегрузка операторов. 25
Конструктор-копировщик. 26
Лекция № 8. Наследование Закрытый. Защищённый Форматированный ввод. Ввод-вывод в файл. 28
Наследование. 28
Инициализация наследуемых классов. 28
Потоки. 29
Управление выводом данных: 30
Лекция № 9. Использование файлов для ввода-вывола. 31
Использование файлов для ввода- вывода информации. 31
Строки. 32
Лекция № 10. . Виртуальные методы. Полиморфизм. 33
Виртуальные методы. 33
Как работают виртуальные функции. 33
Абстрактные классы. 35
Лекция № 11. Специальные классы и функции. Вложение. Делегирование. Классы друзья. Функции -друзья. Связные списки. 36
Статические переменные-члены. 36
. История развития языков Концепции структурного и объектно-ориентированного программирования. особенности написания программ для системы Windows, концептуальные отличия .Составные части программы на С++. Использование функций
Лекция № 1.Основные понятия языка C++. Переменные, константы. Резервирование памяти, инициализация, типы и их значения, символы. Выражения. Операторы. операции. Линейные программы. Операторы отношений. логические операторы. оператор ветвления.
Int main()
{
cout <<”Привет Мир! Меня зовут …n”;
Return 0
}
1. Рассмотрите следующую программу и попытайтесь понять, что она делает, не запуская её на выполнение.
#include <iostream.h>
Int main()
{ int x=5;
int y=7;
cout <<”n”
cout << x+y <<” ”<<x*y;
cout <<”n”
Return 0
}
2 какие ошибки будут при компиляции, почему?
#include <iostream.h>
Int main()
{
cout <<”Привет Мир! Меня зовут …n”
Оператор ветвления if.
Логические операторы.
Схема if( (x==5)
If (условие) выражение;
If(условие)
{
Выражение 1;
Выражение 2;
}
Else
{
Выражение 3;
Int main(void)
{
Else
cout<<"Число "<<fistNumb<<" делится без остатка на "<<secondNumb<<"n";
}
Else
cout<<"Число "<<fistNumb<<" не делится без остатка на "<<secondNumb<<"n";
}
Else
cout<<"Число "<<fistNumb<<" меньше чем "<<secondNumb<<"n";
Return 0;
}
Лекция № 2.Циклы. Счётчики. Указатели. память. размещение объектов в области динамической памяти. ссылки. Адреса. передача аргументов функции как ссылок. возвращение нескольких значений.
Циклы.
Цикл — это блок программы , который необходимо повторить несколько раз. Исторически первые циклы организовывались при помощи оператора безусловного перехода goto;
#include <iostream.h>
Int main(void)
{
int i=0;
loop: i++;
cout << "счётчик ="<<i<<"n";
if(i<5)
Goto loop;
cout <<"конец работыn";
Return 0;
}
Использование оператора goto позволяет написать так называемую “спагетти” плохо читаемую и организованную программу. Поэтому последние 20 лет преподаватели убеждают студентов не использовать этот оператор.
Следующим появился оператор while .в нём выполнение последовательность операторов повторяется пока условие в скобках истино.
#include <iostream.h>
Int main(void)
{
int i=0;
while(i<5)
{
cout <<"счётчик = "<<i<<"n";
I++;
}
cout <<"конец работыn";
Int main(void)
{
for (int i=0;i<10;i++)
cout <<"счётчик = "<<i<<"n";
cout <<"конец работыn";
Return 0;
}
Цикл for работает в такой последовательности:
1. Присваивается начальное значение счётчику ( и другие начальные значения);
2. Вычисляется значение выражения на условия продолжения цикла;
3. Если условие возвращает true, то сначала выполняется тело цикла, а затем заданная операция с счётчиком.
4. шаги 2 и 3 повторяются на каждой итерации цикла.
#include <iostream.h>
Int main(void)
{int I,j;
for ( i=0,j=0;i<3;i++,j++)
cout <<"i= "<<i<<" j="<<j<<"n";
I=j=10;
cout <<”I=”<<I<<” j=”<<j<<”n”;
cout <<"конец работыn";
Return 0;
}
Область видимости счётчика цикла: в случае если счётчик описан в операторе цикла, то он существует только в теле цикла, после выполнения цикла эта переменная перестаёт существовать для компилятора, что бы этого не произошло необходимо описывать счётчики, в блоке описания переменных.
Оператор switch.
Оператор множественного ветвления.
#include <iostream.h>
Int main(void)
{ int number;
cout <<"ВВедите число между 1 и 5: ";
cin >> number;
cout <<"n";
Return 0;
}
Int I;
Int &ri=I; —это ссылка наI,ссылка обязательно должна быть инициализирована, то есть иметь значение, то есть куда-то ссылаться, однажды инициализировав ссылку ей нельзя присвоить другое значение. Нельзя ri=j; так как ri— это синоним i.
Ссылку можно рассматривать как постоянный указатель, который всегда разадресован, то есть его не надо разадресовывать, для того чтобы получить значения по адресу.
Для выделения памяти в области динамического распределения используется оператор new . Для этого подходит строка (тип данных — int) :
Int *page = new int;
Когда память, выделенная под динамическую переменную больше не нужна, то её следует освободить оператором delete имя переменной. При этом переменная указатель сохраняется, но она больше не указывает ни на какой сегмент памяти. Двойное применение delete к одному и тому же указателю приводит к зависанию программы. Поэтому рекомендуется после оператора delete , удалённому указателю присваивать значение 0. С указателями можно производить арифметические действия.
Int *a, b, *c;
*a=b;
c=a++;
с будет указывать на область памяти, следующую за ана 2 байта, так как тип переменной указателя занимает 2 байта.
Лекция № 3.Функции. Объявление и определение функции. выполнение функции. Локальные и глобальные переменные. Аргументы функции — фактические и формальные. Перегрузка функций. возвращаемые значения. Массивы.
Функции.
Int Add(int x, int y);
Int Add(int x,int y)
{
cout << “В Add складываются “ <<x<< “и”<<y<<”n”;
return (x+y);
}
Int main()
{ int a,b,c;
cout <<”Введите два числа:n”;
cin >>a;
cin >> b;
c=Add(a,b);
cout <<”a+b=”<<c<<”n”;
Return 0;
}
Void main(void)
{
int y=5,rez;
printf("квадрат y равен %dn",SQUARE(y)); printf("квадрат y+2 равен %dn",SQUARE(y+2)); printf("частное равно %fn",100./SQUARE(y));
}
Inline int Area(int,int);
Возмоожны рекурсивные функции, то есть функции, вызывающие самое себя.
Пример.
#include <iostream.h>
Int fib(int n);
Int fib(int n)
{ if (n<3)
Return 1;
Else
return (fib(n-2)+fib(n-1));
}
Int main(void)
{
Int i,rez;
cout <<"введите число Фибоначи = ";
cin >> i;
rez=fib(i);
cout <<i<<"-oe число Фибоначи ="<<rez<<"n";
Return 0;
}
Результат
введите число Фибоначи = 6
6-oe число Фибоначи =8
Int main(void)
{
Float a,b,c,x1,x2;
Int rez;
cout <<"Введите числаn a:";
cin >>a;
cout <<"n b=:";
cin >>b;
cout <<"n c=:";
cin >>c;
// вызов функции с фактическими параметрами
rez=sqwere(a,b,c,&x1,&x2);
Switch(rez)
{ case 0: cout << "корней нет n";break;
case 1: cout << "корнь один = "<< x1 <<" n";break;
case 2: cout << "корней два x1= "<< x1 <<" x2= "<<x2<<"n";break;
}
Int main(void)
{
Float a,b,c,x1,x2;
Int rez;
cout <<"Введите числаn a:";
cin >>a;
cout <<"n b=:";
cin >>b;
cout <<"n c=:";
cin >>c;
rez=sqwere(a,b,c,x1,x2);
Switch(rez)
{ case 0: cout << "корней нет n";break;
case 1: cout << "корнь один = "<< x1 <<" n";break;
case 2: cout << "корней два x1= "<< x1 <<" x2= "<<x2<<"n";break;
}
Return 0;
}
Лекция № 4.Массивы. Элементы массива. инициализация массива. объявление массива. Динамические и статические массивы. Многомерные массивы. Строковые.
Randomize();
for(i=0;i<n;i++)
{ for(j=0;j<m;j++)
*(Arrey+i*m+j)=random(zz);
}
Return 0;
}
int exitArrey(int n,int m, int *Arrey)
{ int i;
for(i=0;i<n*m;i++)
(((i+1)%m)==0)? cout<<*(Arrey+i)<<"n" : cout<<*(Arrey+i)<<"t";
Return 0;
}
int* sunArrey(int n,int m,int *Arrey1,int*Arrey2)
{
int*Arrey;
Int i,j;
Arrey=(int*)malloc(sizeof(int)*n*m);
for(i=0;i<n;i++)
for(j=0;j<m;j++)
*(Arrey+i*m+j)=*(Arrey1+i*m+j)+(*(Arrey2+i*m+j));
Return Arrey;
}
VvodArrey(n,m,ArreyF,size);
vvodArrey(n,m,ArreyS,size/2.);
ArreyRez=sunArrey(n,m,ArreyF,ArreyS);
cout <<"******--1--********n";
ExitArrey(n,m,ArreyF);
cout <<"******--2--*********n";
ExitArrey(n,m,ArreyS);
cout <<"******--3--*********n";
ExitArrey(n,m,ArreyRez);
Return 0;
}
Результат работы программы.
Введите размерность массива
по строкам: 2
по столбцам : 3
******--1--********
64 47 73
8 85 53
******--2--*********
32 23 36
4 42 26
******--3--*********
96 70 109
12 127 79
Введите размерность массива
по строкам: 1
по столбцам : 5
******--1--********
70 44 39 57 46
******--2--*********
35 22 19 28 23
******--3--*********
105 66 58 85 69
***Домашнее задание: переписать программу со статическим выделением памяти.
Лекция № 5.Структуры. Доступ к элементам структуры. Инициализация. Выделение памяти. работа с динамическими типами данных . работа со стеком, очередью, деком, деревом. (Самостоятельное изучение)
Шаблон структуры
Шаблон - это схема, описывающая содержание структуры. Установка структурного шаблона телефонный справочник:
struct sprav {
char fio[20];
Структурные переменные
Объявление структурных переменных приводит к выделению памяти для компонент структуры, куда можно записать данные или откуда можно прочитать их. Для объявления структурных переменных имеются несколько способов.
1. Установить структурный шаблон:
struct sprav {
char fio[20];
Long num;
};
Объявить простую переменную, массив структур, указатель на структуру: struct sprav tel1, tel2[5], *tel3;
2. Установить структурный шаблон с помощью макроопределения:
#define SPRAV struct sprav
SPRAV {
char fio[20];
Long num;
};
Объявить переменные:
SPRAV sp1, sp2[6], *sp3;
3. Объявить переменные одновременно с установкой шаблона (если на данную структуру вы больше не ссылаетесь):
struct {
char fio[20];
Long num;
} tel1, tel2[3], *tel3;
4. Ввести новый тип данных (TEL)-структура определенного вида:
typedef struct {
char fio[20];
Long num;
} TEL;
Объявить переменные нового типа:
TEL tel1, tel2[6], *tel3;
Если программа достаточно объемна, представляется более удобным четвертый способ.
Инициализация структуры
Инициализировать можно только внешние или статические структуры.
static struct {
char fio[20];
Long num;
} tel[2]={
"Иванов Ф.А.", 456756,
"Петров В.П.", 632345
};
Доступ к компонентам структуры
Доступ к компонентам структуры продемонстрируем с помощью примеров.
Пример 1.
/* Обращение к элементам структуры через имя переменной */
#include <stdio.h>
#include <conio.h>
Void main(void)
{
struct{
char fio[20]; /* фамилия */
long num; /* телефон */
} tel1, tel2;
Clrscr();
puts("введите фио абонента-");
Long num;
};
Void main(void)
{
struct sprav *tel1, *tel2;
Массив структур
Пример 3.
/* Массив структур. Обращение к элементам структуры через */
/* имя элемента массива */
#include <stdio.h>
#include <conio.h>
#include <string.h>
#define SPRAV struct sprav
Void main(void)
{
SPRAV{
char fio[20];
Long num;
};
SPRAV tel[5]; /* массив структур - 5 элементов */
char fio_tek[20];
Int i;
Clrscr();
/* ввод данных в массив структур */
for(i=0; i<5; i++)
{
puts("введите фио абонента-");
gets(tel[i].fio);
puts("введите его номер-");
scanf("%ld",&tel[i].num);
Getchar();
}
puts("Выбор телефона по фамилии");
Long num;
} TEL;
Void main(void)
{
TEL *tel;
char fio_tek[20];
Int i;
Clrscr();
/* Выделение памяти для массива - 3 элемента */
tel=(TEL *)malloc(sizeof(TEL)*3);
for(i=0; i<3; i++)
{
puts("введите фио абонента-");
gets((tel+i)->fio);
puts("введите его номер-");
scanf("%ld",&(tel+i)->num);
Getchar();
}
puts("Выбор телефона по фамилии");
Gets(fio_tek);
for(i=0; i<5; i++,tel++)
if(!strcmp(fio_tek,tel->fio)) break;
if(i!=5)
printf("номер абонента %s равен %ldn",fio_tek,
tel->num);
Else
puts("Абонент не найден");
}
Void main(void)
{
Return;
}
/* Вычисление суммы двух комплексных чисел */
void sum(COMPLEX *p1,COMPLEX *p2,COMPLEX *p3)
{
(*p3).a=(*p1).a+(*p2).a;
(*p3).b=(*p1).b+(*p2).b;
Return;
}
/* Ввод значений для элементов структуры */
void vvod(COMPLEX *p,float a, float b)
{
p->a=a;
p->b=b;
Return;
}
Вложенные структуры
Структура, являющаяся компонентом другой структуры, называется вложенной.
Пример 6.
/* Даны четыре точки - центры четырех окружностей. Заполнить структуру окружность, если все окружности проходят через начало координат. */
#include<conio.h>
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
struct POINT {
Float x;
Float y;
};
struct CIRCLE {
struct POINT point; /* вложенная структура */
Double r;
} circle[2], *p;
Void main (void)
{
Int i,j;
Float a,b,c,d;
Clrscr();
Gotoxy(17,1);
cputs("ВВЕДИТЕ КООРДИНАТЫ ТОЧЕК :rn");
for(i=0;i<2;i++)
{
cprintf ("nn ВВЕДИТЕ X: ");
cprintf ("X[%d]= ",i+1);
cscanf("%f",&circle[i].point.x);
cprintf ("n ВВЕДИТЕ Y: ");
cprintf ("Y[%d]= ",i+1);
cscanf ("%f",&circle[i].point.y);
}
P=circle;
Gotoxy(17,12);
cputs("РЕЗУЛЬТАТ:rnn");
for(i=0;i<2;i++)
{
a=p->point.x;
b=p->point.y;
c=sqrt(a*a+b*b);
p->r=c;
cprintf("nРАДИУС : %lf ЦЕНТР (%f,%f)rn",p->r,a,b);
P++;
}
Лекция № 6.Базовые классы. Классы и члены. Получение доступа к членам класса. Ограничение доступа к членам класса. определение методов класса. Конструкторы и деструкторы. Вложенные классы. структуры.
Классы.
Новый тип создаётся путём объявления классов. Класс — это просто коллекция переменных, скомбинированная с набором связанных функций. Это совмещение данных и операций над ними в один объект называется инкапсуляция. Данные в классе называют переменными-членами или данными-членами. Функции класса часто выполняют операции над переменными-членами класса и называются функциями-членами или методами класса. Функции члены принадлежат классу так же, как и данные-члены, и определяют функциональные возможности класса.
Для объявления класса используется ключевое слово class. Пример:
Class Cat
{
Unsigned int Age;
Unsigned int Weight;
Void Meow();
};
Объявление класса не резервирует память под данные, здесь только сообщается: о существование класса с таким именем и сколько памяти требуется для каждого объекта этого класса (память выделяется под данные-члены, под методы память не выделяется.
Определение объектов происходит так:
Cat Vaska;
Доступ к членам класса.
Существует оператор прямого доступа (.)
Vaska.Weight =5;
Class Cat
{
Unsigned int Age;
Unsigned int Weight;
Void Meow();
};
а затем в main()
Cat Vaska;
Vaska.Age=5;
Вызовет ошибку компиляции, так как все члены класса Сat закрыты, а присвоение идёт во внешней к классу функции.
Поэтому необходимо сделать:
Class Cat
{public:
Unsigned int Age;
Unsigned int Weight;
Class Mass
{
int *Arrey;
Int n;
public:
Int getSize();
Void putSize(int ss);
Void getArrey(int ras);
Int putArrey();
Void del();
};
void Mass::getArrey(int ras)
{ int i;
Randomize();
Arrey = new int[n];
for(i=0;i<n;i++)
(Arrey+i)=random(2*ras)-ras;
}
int Mass::putArrey()
{ int i;
for(i=0;i<n;i++)
cout<<*(Arrey+i)<<"t";
cout <<"n";
Return 0;
}
int Mass::getSize()
{ return n;
}
void Mass::putSize(int ss)
{n=ss;
}
void Mass::del()
{delete[] Arrey;
}
Int main(void)
{
int ss,m,size=100;
Mass Arrey;
cout <<"Введите размерность массиваn по строкам:";
cin >>ss;
Arrey.putSize(ss);
cout << "размерность массива = "<<Arrey.getSize()<<"n";
Arrey.getArrey(100);
Arrey.putArrey();
Arrey.del();
Arrey.putArrey();
Дополнительные возможности использования функций.
Дополнительные возможности позволяют:
§ Перегружать функции-члены:
§ Перегружать операторы.
§ Создавать функции для поддержания классов с динамическим выделением памяти для переменных.
Мы уже говорили о перегрузке функций на занятии посвящённом функциям.Функции-члены можно перегрузить точно так же.
#include<iostream.h>
Class Rect
{ public:
Rect(int width,int height);
~Rect() {}
Void DrawRect(int aWidth,int aHeight);
Void DrawRect();
private:
Int itsWedth;
Int itsHeight;
};
Rect::Rect(int wedth,int height)
{
itsWedth=wedth;
itsHeight=height;
}
void Rect::DrawRect()
{
DrawRect(itsWedth,itsHeight);
}
void Rect::DrawRect(int aWedth,int aHeight)
{
for(int i=0;i<aHeight;i++)
{
for(int j=0; j<aWedth;j++)
cout<<"*";
cout << "n";
}
}
Int main(void)
{
Rect theRect(30,5);
cout <<"Печать того, что уже естьn";
TheRect.DrawRect();
cout <<"Печать новогоn";
TheRect.DrawRect(40,10);
Return 0;
}
Таким же образом можно перегружать конструкторы.
В конструкторе можно инициализировать члены не в теле, а в момент инициализации самого конструктора, синтаксис выглядит следующим образом:
Rect::Rect(int wedth,int height):
Class Y
{
void f1(X&);
void f2(X*);
};
Class X
{
Friend Y;
Int I;
Void f3();
}
Перегрузка операторов.
Форма для перегрузки операторов:
Объявление перегруженных операторов осуществляется так же, как и функций. Используется специальное слово: operator , за которым следует сам перегружаемый оператор. В функциях с одним операндом параметры не задаются
Const класс & класс::operator …();
Перегрузка оператора с двумя операндами требует наличия параметров (константные ссылки на объекты этих классов):
Класс класс::operator + (const класс &rhs) — заголовок и след. Описание
Класс operator + (const класс &)
Рекомендации:
§ перегружайте операторы. Если код программы после этого станет чётче и понятнее.
§ Возвращайте объекты класса из перегруженных операторов.
§ Не увлекайтесь созданием перегруженных операторов, выполняющих несвойственные им функции.
#include<iostream.h>
Class V_3d
{
V_3d c;
c.x=x+t.x; c.y=y+t.y; c.z=z+t.z;
Return stream;
}
istream &operator >>(istream &stream,V_3d &t)
{
stream >>t.x>>t.y>>t.z;
Return stream;
}
double V_3d:: mod()
{
return x*x+y*y+z*z;
}
Void main(void)
{
V_3d a;
V_3d b(4,7,10);
V_3d c(b);
cout << "координаты вектора b: n";
cout <<b;
cout << "координаты вектора c: n";
C.print();
cout <<"введите координаты вектора a:n";
cin >>a;
cout << "координаты вектора а: n";
cout <<a;
c=a+b;
cout << "координаты вектора a+b n";
C.print();
}
Результат работы программы:
координаты вектора b:
x=4,y=7,z=10
координаты вектора c:
x=4 y=7 z=10
введите координаты вектора a:
-1 3 6
координаты вектора а:
x=-1,y=3,z=6
координаты вектора a+b
x=3 y=10 z=16
Class base
{ int x;
public:
void setx(int n){x=n;}
void prinx(){cout<<"x="<<x<<"n";}
};
class deriv : private base
{
Int y;
public:
void setxy(int n,int m){setx(n);y=m;}
void prinxy(){prinx();cout<<"y="<<y<<"n";}
};
Void main(void)
{
Deriv ob;
cout <<"результат работы программы: n" ;
Ob.setxy(10,25);
Ob.prinxy();
}
результат работы программы:
X=10
y=25
Инициализация наследуемых классов.
Все действия по инициализации объектов выполняет конструктор порождённого класса.
Если конструктору базового класса требуются аргументы, то они должны быть указаны в списке аргументов конструктора. В общем виде конструктор имеет вид:
Конструктор_производного_класса(список аргументов): базовый_класс1( список аргументов)…базовый_класс_N (список аргументов) { тело конструктора}
Производный класс может иметь не один , а несколько базовых. В этом случае базовые классы указываются списком, через ,.
#include <iostream.h>
Class B1
{ public:
B1(){cout<<"работа конструктора B1n";}
~B1(){cout<<" работа деструктора B1n";}
};
Class B2
{ public:
B2(){cout<<"работа конструктора B2n";}
~B2(){cout<<" работа деструктора B2n";}
};
class D:public B1,public B2
{
public:
D(){cout<<"работа конструктора Dn";}
~D(){cout<<" работа деструктора Dn";}
};
Void main(void)
{
cout <<"результат работы программы: n" ;
D ob;
cout<<"*********************n" ;
}
результат работы программы:
Работа конструктора B1
Работа конструктора B2
Работа конструктора D
*********************
Работа деструктора D
Работа деструктора B2
Работа деструктора B1
Конструкторы базового класса должны быть объявлены с атрибутами protected или publicдля того, чтобы обеспечить возможность их вызова из класса-наследника.
Int main(void)
{
Char ch;
while((ch=cin.get())!=EOF)
{
cout << "ch: "<<ch<<endl;
}
cout <<"n конец n";
Int main(void)
{
Char ch;
cout <<"введите фразу: ";
While(cin.get(ch))
{
if(ch=='!') cin.putback('$');
else cout <<ch;
while(cin.peek()=='#')
cin.ignore(1,'n');
}
F1.close();
F2.close();
#include<fstream.h>
#include<iostream.h>
Void main(void)
{ char ch;
int num=0;
char buffer[255];
ofstream fout("rez.txt");
cout<<"результат работы программы: n";
cin.ignore(1,'n');
Cin.getline(buffer,255);
fout<<buffer<<"n";
Fout.close();
ifstream fin("rez.txt");
fin.unsetf(ios::skipws);
while(!fin.eof())
{fin>>ch;
cout<<ch;
num++;
}
cout <<"n файл закончилсяn число символов :"<<num<<"n";
Fin.close();
}
результат работы программы:
укнеку нгшгнш №;%435435прорлорл рорлордло олодлод
кнеку нгшгнш №;%435435прорлорл рорлордло олодлод
Файл закончилс
число символов :50
Switch(i)
{
case 0: cout <<"они равныn";break;
case-1: cout <<"1-ое меньшеn";break;
case 1: cout <<"1-ое большеn";break;
}
}
Int main(void)
{
char stroka[80],*ptr,string[80],c='*';
Int i;
cout<<"/*результат работы программыn";
cout <<"Введите строку:";
cin >>stroka;
Srav(string,stroka);
Srav(stroka,stroka);
Srav(stroka,string);
ptr = strchr(stroka, c); //проверка на вхождение символа.
If (ptr)
cout << "Символ "<< c <<" находится на " << ptr-stroka+1 << "позицииn" ;
Else
cout<<"Этого символа нет в строке";
cout<<"*//";
Return 0;
}
Результат работы программы
Введите строку: Привет
длина строки Привет=6
_______Привет
*******Привет
^^^^^^^Привет* Это Я
1-ое: Привет,2-ое:Привет* Это Я
Ое меньше
1-ое: Привет* Это Я,2-ое:Привет* Это Я
Они равны
1-ое: Привет* Это Я,2-ое:Привет
Ое больше
Символ * находится на 7позиции
Лекция № 10.. Виртуальные методы. Полиморфизм.
Class X
{ public:
Virtual double A(double x)
{ return x*x; }
Double B(double x)
{ cout<<A(x)<<":2=";
return A(x)/2.; }
};
class Y:public X
{ public:
Double A(double x)
{ return x*x*x; }
};
Int main(void)
{
Y y;
X x;
cout<<"при x=3."<<endl;
cout<<x.B(3.)<<" X"<<endl;
cout<<y.B(3.)<<" Y"<<endl;
}
результат выполнения программы:
при x=3.
9:2=4.5 X A::X=x*x;
27:2=13.5 Y A::Y=x*x*x
Специфической особенностью указателей на классы в С++ является то, что указатель объявленный, как указатель на базовый класс может использоваться, как указатель на любой класс, производный от этого базового. Компилятор при вызове виртуальной функции определяет класс объекта для которого вызывается виртуальная функция и подбирает соответствующую версию функции.
#include<iostream.h>
Class Mammal
{ public:
Mammal():itsAge(1){}
virtual ~Mammal() {}
virtual void Speak() { cout<< " Млекопитающее что-то сказало!n";}
protected:
Int itsAge;
};
class Dog:public Mammal
{ public:
void Speak(){cout<<"Гафф!n";}
};
class Cat:public Mammal
{ public:
void Speak(){cout<<"Мурр!n";}
};
Void VFunc(Mammal);
void PFunc(Mammal*);
void RFunc(Mammal&);
Int main(void)
{
Mammal *prt=0;
Int choice;
While(1)
{
bool fQ=false;
cout<<"1--собака, 2-- кошка, иначе-- млекопитающее, 0-- выход.";
cin>> choice;
Switch(choice)
{
case 0: fQ=true;break;
case 1: prt=new Dog; break;
case 2: prt=new Cat; break;
default: prt=new Mammal;
}
If(fQ) break;
cout<<"указатель на класс: " ; Pfunc(prt);
cout<<"ссылка на класс: "; Rfunc(*prt);
cout<<"переменная класса: -- "; VFunc(*prt);
}
Return 0;
}
Void VFunc(Mammal M)
{ MV.Speak(); }
void PFunc(Mammal *pM)
{ pM->Speak(); }
void RFunc(Mammal &rM)
{ rM.Speak(); }
/* результат работы программы:
Собака, 2-- кошка, иначе-- млекопитающее, 0-- выход. 1
указатель на класс: -- Гафф!
ссылка на класс: -- Гафф!
переменная класса: -- Млекопитающее что-то сказало!
Собака, 2-- кошка, иначе-- млекопитающее, 0-- выход. 2
указатель на класс: -- Мурр!
ссылка на класс: -- Мурр!
переменная класса: -- Млекопитающее что-то сказало!
Собака, 2-- кошка, иначе-- млекопитающее, 0-- выход. 3
указатель на класс: -- Млекопитающее что-то сказало!
ссылка на класс: -- Млекопитающее что-то сказало!
переменная класса: -- Млекопитающее что-то сказало!
Абстрактные классы.
Очень часто виртуальная функция, объявленная в базовом классе, никогда не используется в нём, то есть она представляется в виде пустой функции ( { } ).
Версия виртуальной функции, которая должна быть определена, но никогда не будет использоваться, должна быть объявлена как чисто виртуальная :
Virtual тип имя_функции (список параметров) =0;
При выполнении в программе число виртуальной функции генерируется сообщение об ошибке и программа аварийно завершается (при работе пустой функции этого не происходит).
Класс с одной или большим количеством чисто виртуальных функций называется — абстрактным. Правила языка С++ запрещают использование таких классов, они могут использоваться только как базовые для создания других классов. Это происходит потому, что одна или несколько функций для объектов этого класса не имеют определения. Данная ситуация используется для обнаружения ошибок создания фиктивных объектов при помощи компилятора.
Рекомендации:
§ Используйте абстрактные типы данных для создания для создания общего интерфейса для всех производных классов.
§ Обязательно замещайте в произвольных классах чистые виртуальные функции.
§ Объявляйте все функции, которые требуют замещения в произвольном классе как виртуальные.
§ Не пытайтесь создать объект абстрактного класса.
Лекция № 11.Статические переменные. Шаблоны функций и классов. Связные списки.
Class Cat
{
public:
Cat(int age):itsAge(age){HayMenyCats++;}
virtual ~Cat(){HayMenyCats--;}
virtual int GetAge() {return itsAge;}
virtual void SetAge(int age){itsAge=age;}
Static int HayMenyCats;
private:
Int itsAge;
};
int Cat::HayMenyCats =0;
Int main(void)
{
const int MaxCat=5;
Int i;
Cat *CatHouse[MaxCat];
for(i=0;i<MaxCat;i++)
CatHouse[i]=new Cat(Maxcat-i);
for(i=0;i<MaxCat;i++)
{
cout<<"сейчас у нас ";
cout<<Cat::HayMenyCats;
cout<<" кота.n";
cout<<"удалим кота, возраст которого ";
cout<<CatHouse[i]->GetAge()<<" года n";
delete CatHouse[i];
CatHouse[i]=0;
}
Return 0;
}
у нас живёт 4 кота .
Удалим кота, возраст которого 4 года
у нас живёт 3 кота .
Удалим кота, возраст которого 3 года
у нас живёт 2 кота .
Удалим кота, возраст которого 2 года
у нас живёт 1 кота .
Class Cat
{
public:
Cat(int age) :itsAge(age) {HayMenyCats++;}
virtual ~Cat(){HayMenyCats--;}
virtual int GetAge() {return itsAge;}
virtual void SetAge(int age) {itsAge=age;}
Static int GetHayMeny()
{ return HayMenyCats;}
private:
Int itsAge;
Static int HayMenyCats;
};
Void Info();
int Cat::HayMenyCats =0;
Int main(void)
{
const int MaxCat=4;
Int i;
Cat *CatHouse[MaxCat];
for(i=0;i<MaxCat;i++)
{
CatHouse[i]=new Cat(MaxCat-i);
Info();
cout<<CatHouse[i]->GetAge()<<" годаn";
}
for(i=0;i<MaxCat;i++)
{ cout<<"удаляем старшего кота n"<<endl;
delete CatHouse[i];
CatHouse[i]=0;
Info();
}
Return 0;
}
Шаблоны функций и классов
Шаблоны представляют ещё одну реализацию полиморфизма в программах С++. Они позволяют создать универсальный фрагмент кода, а затем использовать его многократно с различными типами данных или различными объектами. С помощью шаблонов можно уменьшить объём и сложность программы.
Шаблоны функций позволяют передавать в качестве аргумента тип переменной. Шаблоны создают семейства функций, определяющее неограниченное множество родственных функций. Экземпляризация— операция создания определённого типа из шаблона. Отдельные классы называются экземплярами шаблона. Параметризованные шаблоны — представляют возможность создания общего класса и для построения конкретных экземпляров передают этому классу в качестве параметров типы данных.
На пример список. Список может быть для чего угодно.
Построение шаблонов рассмотрим на примере. Необходимо написать функцию расчёта куба для аргумента. (Cub()).
#include<iostream.h>
#include<math.h>
template <class T>
T cub(T x)
{ return x*x*x;}
template <class SwapType>
void Swap(SwapType &x,SwapType &y)
{ SwapType tmp;
tmp=x;
X=y;
y=tmp;
}
template <class T1,class T2>
T1 max(T1 x,T2 y)
{
if(x>y)return x;
Else return y;
}
Шаблоны классов.
Шаблон класса представляет собой скелет обобщённого класса. Ситаксис такой:
Template< список_аргументов_шаблона>
{
//тело класса
};
Каждый аргумент в списке является либо объявлением типа float a; либо идентификатором класса class T. Из-за этого определение функции-метода шаблонного класса имеет вид:
Template< список_аргументов_шаблона>
Тип_результата имя_класса < список_аргументов_шаблона>::
Имя_функции( список_аргументов_функции)
{
//тело функции.
}
объявление объекта шаблонногокласса:
имя_класса_шаблона < список_аргументов_шаблона> имя_объекта;
Пример использования шаблонов будем рассматривать на создании очереди.
Class Data
{
public:
Data ();
~Data(){delete fam;}
int Compare(const Data &);
Void Show();
private:
char fam[25];
Float ball;
};
Data::Data()
{
cout<<"n Введите фамилию и средний балл :";
cin>>fam>>ball;
}
void Data::Show()
{ cout.width(25);
cout.fill(' ');
cout<<fam;
Cout.width(10);
cout.fill('-');
Cout.precision(3);
cout<<ball<<"n";
Fout.width(25);
fout.fill(' ');
fout<<fam;
Fout.width(10);
fout.fill('-');
Fout.precision(3);
fout<<ball<<"n";
//fout<<fam<<"--"<<ball<<endl;
}
int Data::Compare(const Data &theO)
{
if(strcmp(fam,theO.fam)<0)return -1;
if(strcmp(fam,theO.fam)==0)return 0;
if(strcmp(fam,theO.fam)>0)return 1;
}
Class Node;
Class HeadNode;
Class TailNode;
Class InternalNode;
MyData(theData),myNext(next)
{}
Node* InternalNode ::Insert(Data *theData)
{
int result=myData->Compare(*theData);
Switch(result)
{
case 0:
case1:{InternalNode *dataN=new InternalNode (theData,this);
return dataN;}
case-1:{myNext=myNext>Insert(theData);
return this;}
}
Return this;
}
class TailNode:public Node
{
public:
TailNode(){}
~TailNode() {}
virtual Node* Insert(Data *theData);
virtual void Show(){ }
private:
};
Node* TailNode::Insert(Data *theData)
{
InternalNode *dataN=new InternalNode (theData,this);
Return this;
}
Class Admin
{public:
Admin();
~Admin(){delete myHead;}
void Insert(Data* pData);
void ShowAll(){myHead->Show();}
private:
HeadNode* myHead;
};
Admin::Admin()
{
myHead=new HeadNode;
}
void Admin:: Insert(Data*pData)
{
myHead->Insert(pData);
}
Int main()
{
Data* pData;
int val=1;
Admin ll;
while(val!=0)
{
pData=new Data();
Ll.Insert(pData);
cout<<"хотите закончить ввод? Если да, то введите 0";
cin >>val;
}
Ll.ShowAll();
cout<<"********************************n";
Fout.close();
Return 0;
}