Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции.docx
Скачиваний:
14
Добавлен:
23.03.2015
Размер:
63.56 Кб
Скачать

m_fat@mail.ru

Лекция: шаблоны функций

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

#include ’fdkjf’

……………………..

#include <ghdfg>

int square (int x)

{return x*x}

double square (double y)

{return y*y}

main ()

{

cout <<”квадрат целого числа 7 равен”<<square(7)<<endl<<”квадрать числа 7,5 типа double=”<<square(7.5)<<endl;

return();

}

(Вопросы к контрольной: массивы, типы переменных, инкременты, шаблоны функции)

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

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

//шаблон функции

#include "stdafx.h"

#include <conio.h>

#include <iostream>

#include <locate>

#include <cstdlib>

using namespace std;

template <class T>

T maximum (T value1, T value2, T value3)//задаём функцию

{

T max = value1; //ищем максимум, сравнвая числа с большим числом

if (value2>max)

max = value2;

if (value3>max)

max = value3;

return max;

}

int main ()

{

setlocale(LC_ALL,"russian"); //подключаем русский язык

int int1, int2, int3;//задаём переменные

cout<<"введите три целых значения:";//выводим на экран фразу в кавычках

cin>>int1>>int2>>int3;//вводим значения с клавиатуры

cout<<"max="<<maximum(int1,int2,int3)<<"\n";//вызываем функцию

double a,b,c; //то же самое что и выше

cout<<"введите три не целых значения:";

cin>>a>>b>>c;

cout<<"max="<<maximum(a,b,c);

getch();

return 0;

}

Формула среднего значения: Xrmg=(sqrt(x12+x22+..+xn2))/n

ДЗ: на телефоне

№1

//скорость студентов

#include "stdafx.h"

#include <conio.h>

#include <iostream>

#include <math.h>

using namespace std;

template <class T>

T studenty (T a1, T a2,T a3)//задаём функцию

{

T x=sqrt((a1*a1+a2*a2+a3*a3)/3);

return x;

}

int main()

{

setlocale(LC_ALL,"russian"); //подключаем русский язык

double x,y,z;//задаём переменные

cout<<"введите скорость студентов:\n";//выводим на экран фразу в кавычках

cin>>x>>y>>z;//вводим значения с клавиатуры

cout<<"скорость = "<<studenty(x,y,z);//вызываем функцию

getch();

return 0;

}

Прототипы ф-ций дают возможность компилятору проверить правильно ли названы ф-ции. Компилятор игнорит имена переменных упомянутые в прототипе ф-ции. Каждая стандартная библиотека имеет соответствующие заголовочные ф-лы, содержащие прототипы всех ф-ций этой библиотеки., а также определения различных символьных констант необходимых для этой ф-ции. Программист должен создавать свои заголовочные ф-лы. Если аргумент передаётся в ф-цию по значению, созданная копия значения переменной, и именно она предаётся вызываемым ф-циям. Изменение копий вызываемой ф-ции не влияет на значения исходной переменной. Ф-ция Rand генерирует целое число из интервала от 0 до Rand_max равная 32 767.

<stdlib.h> для rand_ .

Указатели и ссылки

Компилятор обрабатывает оператор определения переменной int i, при этом он выделяет память в соответствии с типом integer и инициализирует её значением i=10. Указатель предназначен для хранения адресов области памяти. В с++ выделяют 3 типа указателей: на объект, на функцию, на void. Указатель не является типом, он всегда связан с каким-либо другим объектом. Указатель на функцию содержится адрес в сегменте кода в котором располагается исполняемый код ф-ции, то есть адрес по которому передаётся управления и вызова ф-ции. Указатель на ф-ции используется для косвенного вызова ф-ции(через адрес), а также для передачи имени ф-ции другой ф-ции в качестве параметра. Указатели ф-ции имеют тип «указатель ф-ции возвращающей значения данного типа и имеющих аргументы данного типа» Задание указателя:

Тип(*имя)(список_типов_аргументов)

int(*name)(double,double)

Указатель на объект содержит адрес области памяти в которой хранятся данные определённого типа «основного или составного». Простейший способ объявления указателя на объект имеет вид тип*имя, где тип может быть любым кроме ссылки и битого поля, причём тип может быть к тому моменту может быть объявлен, но не определён. * относится к нему, поэтому чтобы объявить несколько указателей нужно ставить каждому из них. int *a,b,*c – здесь описывается

Размер указателя зависит от модели памяти. Указатель на void применяется в тех случаях, когда конкретный тип объекта, адрес которого требуется хранить, не определён. Указателю на void можно присвоить значения указателя любого типа, а также сравнить его с любыми указ, но перед выполнением каких либо действ с памяти требуется преобразовать его к конкретному типу явным образом.

Инициализация указателей

Указатели чаще всего используется для работы с динамической памятью называемой кучей(heap). Это свободная память, в которой можно во время выполнения программы выделять место в соответствии с потребностями и доступ к выдел участкам динамической памяти (динамические переменные – живут до явного освобождения памяти) производится только через указатели. Непреднамеренное использование нецелезированного указателей распространённая ошибка программиста. Инициализатор записывается после имени указателя.

&-унарная операция, которая возвращает адрес своего операнда.

yPtr=&y возвращает адрес переменной

Int*(*p[10])(); – указатель на массив без параметров

5 4 2 1 3 – последовательность чтения массива компилятором

Правила «Изнутри наружу»:

  1. Если справа от имени имеются квадратные скобки, это массив, если круглые – это функции;

  2. Если слева есть звёздочка, это указатели на проинтерпретированную ранее конструкцию;

  3. Если справа «)» необходимо применить правила внутри скобок, а затем переходить наружу.

void f(int a)){…}

void(*Pf)(int) //указатель на функцию

Pf=f //ссылка на функцию

Выражения и арифметические действия с указателями

С указателями может выполняться опр кол-во операции. Указатели можно увеличить с помощью инкремента, складывать с ним целые числа, вычитать, или вычитать один указатель из другого (осторожно). Допустим что объявлен массив int V[10] и его первый элемент находится в ячейке 3000.

V[0]

V[1]

V[2]

V[3]

V[4]

Переменная указатель vPtr

Начальное значение задаётся путём указания на V[0], t.e. VPtr=3000.

Указатель VPtr можно было дать начальное значение на массив b с помощью одного из след операторов. В общепринятой арифметике сложение 3000+2=3002, но это не в случаи указателей. Когда цело склад или вычит из указатель, он не просто увелич или уменьш на это целое, но это целое предварительно умножается на размер объекта, на который ссылается указатель. Кол-во байтов зависит от количества данных.(3000|3000+8*4, где целое хранится в 4х байтах памяти).

V[0]

V[1]

V[2]

V[3]

V[4]

3000 3004 3008 3012 3016

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

int a=5;//целая переменная

int* p=&a;//в указатель записывается адрес а

int* p (&a);//то же самое другим способом

int* rt=p;//с помощью значения другого инициализированного указателя

int b[10];//массив

int* t=b;//присваивание адреса начала массива

Разность двух указателей эт разность двух значений делённое на размер типа в байтах.(В применении к массиву разность указателей на 3 и 6 эл массива =3) .

Суммирование 2х указателей не допускается.

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

В качестве примера смотрим послед. действий заданных в операторе:*p++=10.

Операции разадресации и инкремента имеют одинаковый приоритет и выполняются справа налево, но т.к. у нас постфикс он выполняется после операции присваивания. Таким образом сначала по адресу записываемому в указателе р будет записано значение 10, а затем указатель будет увеличен на количество байт соответствующих его типу.(*р=10, р++).

Выражение при такой записи (*р)++ инкримирует *р.