Модульное программирование. Шаблоны функций

Содержание

Слайд 2

Перегрузка функций

Перегрузка функций
Часто бывает удобно, чтобы функции, реализующие один и тот же

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

Слайд 3

Перегрузка функций

Использование нескольких функций с одним и тем же именем, но с

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

Слайд 4

Перегрузка функций

Тип возвращаемого результата в разрешении не участвует.
Рассмотрим примеры:
int max(int, int);
int max(int,

Перегрузка функций Тип возвращаемого результата в разрешении не участвует. Рассмотрим примеры: int
*char);
long max(char *, int);
char *max(char *, char *);

Слайд 5

Перегрузка функций

При вызове функции компилятор выбирает соответствующий типу фактических параметров вариант функции.
Если

Перегрузка функций При вызове функции компилятор выбирает соответствующий типу фактических параметров вариант
точного соответствия не найдено, выполняется преобразования в соответствие со стандартом языка, например, bool и char в int, float в double, etc. Далее выполняются преобразования, заданные пользователем, а также поиск соответствий за счет параметров по умолчанию.

Слайд 6

Перегрузка функций

Если ни одного соответствия не найдено, выдается диагностическое сообщение об ошибке.
Неоднозначность

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

Слайд 7

Перегрузка функций

Следующие функции нельзя считать перегруженными:
int max(int, int);
double max(int, int);
long max(int, const

Перегрузка функций Следующие функции нельзя считать перегруженными: int max(int, int); double max(int,
int);
int max(int, int &);

Слайд 8

Перегрузка функций

Следующий пример показывает неоднозначность при наличии параметров по умолчанию.
int f(int a){return

Перегрузка функций Следующий пример показывает неоднозначность при наличии параметров по умолчанию. int
a;}
int f(int a, int b=1){return a*b;}
сout << f(10,2); // вызывается f(int a, int b=1)
сout << f(10); // неоднозначность

Слайд 9

Перегрузка функций

Неоднозначность возникает при неопределенности преобразований, например,
float f(float);
double f(double);
f(10); // к какому типу

Перегрузка функций Неоднозначность возникает при неопределенности преобразований, например, float f(float); double f(double);
преобразовывать, к типу float или double ?

Слайд 10

Перегрузка функций

- функции не могут быть перегруженными, если описание их параметров отличается

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

Слайд 11

Шаблоны функций

*Шаблоны функций
В С++ есть мощное средство параметризации алгоритма – шаблоны функций.

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

Слайд 12

Шаблоны функций

Общий формат объявления шаблонной функции:
template заголовок
{
// тело функции
}
-

Шаблоны функций Общий формат объявления шаблонной функции: template заголовок { // тело
список параметров шаблона.
Слово class в списке заменимо на слово typename.

Слайд 13

Шаблоны функций

В общем случае список шаблона может содержать несколько типов, например,
template

Шаблоны функций В общем случае список шаблона может содержать несколько типов, например,
class B, int i> void f()
{
// ….
}

Слайд 14

Шаблоны функций

В качестве первого примера шаблона функции вспомним функцию swap:
template
void

Шаблоны функций В качестве первого примера шаблона функции вспомним функцию swap: template
swap(Type &arg_1, Type &arg_2)
{
Type temp;
temp = arg_1;
arg_1 = arg_2;
arg_2 = temp;
}

Слайд 15

Шаблоны функций

Вызов этой функции может быть осуществлен двумя способами:
- как вызов обычной

Шаблоны функций Вызов этой функции может быть осуществлен двумя способами: - как
функции без спецификации параметров шаблона
int a=10, b=20;
swap(a,b);
double x=3.45, y=-5.88;
swap(x,y);

Слайд 16

Шаблоны функций

- со спецификацией параметров шаблона
int a=120, b=-45;
swap(a,b);
Обратите внимание на то, что

Шаблоны функций - со спецификацией параметров шаблона int a=120, b=-45; swap (a,b);
после имени функции перед списком фактических параметров в угловых скобках указывается список «фактических» типов параметров шаблона. Если предполагается несколько типов, в списке их нужно перечислить через запятую.

Слайд 17

Шаблоны функций

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

Шаблоны функций В качестве параметров шаблона функции могут выступать как стандартные типы,
и типы, определенные пользователем. Однако здесь необходимо учитывать особенность, что в типе данных, определенных пользователем (структура, класс), необходимо перегрузить те операции, которые использует шаблонная функция.

Слайд 18

Шаблоны функций

Рассмотрим пример
class Test
{
protected:
float test;
public:
Test(){};
Test(float ):test(t){};
Test operator *(const Test &t)
{ return this->test*t.test;

Шаблоны функций Рассмотрим пример class Test { protected: float test; public: Test(){};
}
friend ostream &operator <<(ostream &, const Test &);
};

Слайд 19

Шаблоны функций

ostream &operator <<(ostream &out, const Test &t)
{
out << t.test;
return out;
}
// шаблон

Шаблоны функций ostream &operator { out return out; } // шаблон функции
функции умножения
template Type
mult(Type arg_1, Type arg_2)
{ return arg_1*arg_2; }

Слайд 20

Шаблоны функций

// вызов функции для пользовательского типа
Test tst_1(3.4F), tst_2(-4.55F);
cout << mult(tst_1,tst_2) <<

Шаблоны функций // вызов функции для пользовательского типа Test tst_1(3.4F), tst_2(-4.55F); cout
endl;
Как говорилось ранее, можно явно указать тип передаваемого параметра
cout << mult(tst_1,tst_2) << endl;

Слайд 21

Шаблоны функций

Этот шаблон может быть использован и при работе со стандартными типами

Шаблоны функций Этот шаблон может быть использован и при работе со стандартными
данных:
float f_1 =1.11F, f_2=3.33F;
cout << mult(f_1,f_2) << endl;
Большую возможность предоставляют шаблонные классы, которые позволяют параметризировать не только алгоритм, но и типы данных, с которыми работают эти алгоритмы.

Слайд 22

Шаблоны функций

Рассмотрим пример несложного шаблонного класса.
template class Test
{
protected:
Type test;
public:
Test(){};
Test(Type t):test(t){};
Test operator

Шаблоны функций Рассмотрим пример несложного шаблонного класса. template class Test { protected:
*(const Test &t);
friend ostream &operator << <>(ostream &, const Test &);
};

Слайд 23

Шаблоны функций

Реализация составных и дружественных функций шаблонного класса:
template
ostream &operator <<(ostream &out,

Шаблоны функций Реализация составных и дружественных функций шаблонного класса: template ostream &operator
const Test &t)
{
out << t.test;
return out;
}
template
Test Test:: operator *(const Test &t)
{
return this->test*t.test;
}

Слайд 24

Шаблоны функций

Объявление объектов шаблонных классов и их использование:
Test tst_int_1=10, tst_int_2=200;
cout << tst_int_1*tst_int_2

Шаблоны функций Объявление объектов шаблонных классов и их использование: Test tst_int_1=10, tst_int_2=200;
<< endl;
Test tst_double_1(77.84), tst_double_2(4.1);
cout << tst_double_1*tst_double_2 << endl;

Слайд 25

Шаблоны функций

Функция в качестве возвращаемого результата
Мы знаем, что функция не может вернуть

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

Слайд 26

Шаблоны функций

#include
using namespace std;
double mult(double d)
{
return d*2;
}
typedef double (*PF)(double);

Шаблоны функций #include using namespace std; double mult(double d) { return d*2; } typedef double (*PF)(double);

Слайд 27

Шаблоны функций

PF func()
{
return mult;
}
int main()
{
PF ptr_fun = func();
cout << ptr_fun(55.6478) << endl;
return

Шаблоны функций PF func() { return mult; } int main() { PF
0;
}

Слайд 28

Функция main

Функция, которой передается управление после запуска (вызова) программы на исполнение, должна

Функция main Функция, которой передается управление после запуска (вызова) программы на исполнение,
иметь имя main. Она может возвращать результат в вызвавшую ее систему (операционную систему) и принимать параметры из внешнего окружения.

Слайд 29

Функция main

Стандарт предусматривает два формата функции:
тип main()
{ // ……. }
тип main(int argc,

Функция main Стандарт предусматривает два формата функции: тип main() { // …….
char *argv[])
{ // ……..}
Тип результата int. Возвращаемое значение – 0.

Слайд 30

Функция main

Пример вызова функции main с параметрами из командной строки:
d:\CPP\program_main.exe one two

Функция main Пример вызова функции main с параметрами из командной строки: d:\CPP\program_main.exe one two three
three

Слайд 31

Директивы препроцессора

* Директивы препроцессора
Препроцессором называется первая фаза компиляции. Инструкции (команды) препроцессора называются

Директивы препроцессора * Директивы препроцессора Препроцессором называется первая фаза компиляции. Инструкции (команды)
директивами. Они должны начинаться с символа ‘#’.
Директива include
Директива include<имя_файла> осуществляет подстановку указанного файла в точку, где она записана.

Слайд 32

Директивы препроцессора

Поиск указанного файла начинается со стандартного каталога include, имеющегося в любой

Директивы препроцессора Поиск указанного файла начинается со стандартного каталога include, имеющегося в
реализации языка. После чего осуществляется поиск в текущем каталоге.
Пользователь может заставить препроцессор искать включаемый файл с текущего каталога, если имя укажет в двойных кавычках: #include”name_file.h”

Слайд 33

Директивы препроцессора

Заголовочные файлы обычно имеют расширение h и могут содержать:
- определение типов,

Директивы препроцессора Заголовочные файлы обычно имеют расширение h и могут содержать: -
встроенных функций, шаблоны, перечисления;
- объявления (прототипы) функций, данных, имен, шаблонов;
- пространства имен;
- директивы препроцессора;
- комментарии.

Слайд 34

Директивы препроцессора

В заголовочных файлах не должно быть определение функций и данных. Их

Директивы препроцессора В заголовочных файлах не должно быть определение функций и данных.
принято выносить в файлы реализации. Это не требования языка, это рекомендация.
При указании имен файлов стандартной библиотеки расширение можно опускать. Для большинства старых версий файлов, заимствованных от языка С, в языке С++ есть аналоги файлов без расширения, например,
stdlib.h и cstdlib, stdio.h и cstdio, и т.д.

Слайд 35

Директивы препроцессора

#include”file_name.h”
file_name_main.cpp
Файл основной программы, содержащий функцию main

file_name_1.cpp
file_name_2.cpp
………………………….
file_name_n.cpp
Файлы реализации

file_name.h
Заголовочный файл(ы)

Директивы препроцессора #include”file_name.h” file_name_main.cpp Файл основной программы, содержащий функцию main file_name_1.cpp file_name_2.cpp

Слайд 36

Директивы препроцессора

Директива #define
Директива define определяет подстановку в тексте программы. Она используется для

Директивы препроцессора Директива #define Директива define определяет подстановку в тексте программы. Она
определения:
- символических констант:
#define имя текст_подстановки,
Например,
#define PI 3.14
В любом контексте символьная константа PI будет интерпретироваться как число 3.14.

Слайд 37

Директивы препроцессора

- макросов, которые выглядят как функции, но реализуются подстановкой из текста

Директивы препроцессора - макросов, которые выглядят как функции, но реализуются подстановкой из
в текст программы:
#define имя(параметры) тект_подсановки
Например,
#define sqr(x) (x*x)
Использование макросов вносит свои сложности в программы, в частности, особенности передачи аргументов.

Слайд 38

Директивы препроцессора

Например, для описанного макроса вызов cout << sqr(y+1) << endl;
приведет

Директивы препроцессора Например, для описанного макроса вызов cout приведет к получению числа
к получению числа 6, для правильного ответа нужно вызвать следующим образом
cout << sqr((y+1)) << endl;
Макросы и символические константы заимствованы из языка С, в С++ они не получили широкого применения.

Слайд 39

Директивы препроцессора

- символов, управляющих условной трансляцией. Они используются совместно с директивами #ifdef

Директивы препроцессора - символов, управляющих условной трансляцией. Они используются совместно с директивами
и #ifndef.
Общий формат:
#define имя
Например,
#define VERSION 1
#define h_file “head_file.h”

Слайд 40

Директивы препроцессора

Имена, объявляемые через директиву define рекомендуется писать прописными символами, чтобы зрительно

Директивы препроцессора Имена, объявляемые через директиву define рекомендуется писать прописными символами, чтобы
отличать их от других программных объектов (переменных, функций).

Слайд 41

Директивы препроцессора

Директивы условной трансляции
Директивы условной трансляции #if, #ifdef, #ifndef применяются для того,

Директивы препроцессора Директивы условной трансляции Директивы условной трансляции #if, #ifdef, #ifndef применяются
чтобы исключить компиляцию отдельных частей программы. Это бывает полезно при отладке или при поддержке нескольких версий программ для различных платформ.

Слайд 42

Директивы препроцессора

Формат директивы #if:
#if константное_выражение
…..
[ #elif константное_выражение ]
…..
[ #elif константное_выражение ]
……
[ #else

Директивы препроцессора Формат директивы #if: #if константное_выражение ….. [ #elif константное_выражение ]
]
#endif

Слайд 43

Директивы препроцессора

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

Директивы препроцессора Исключаемые блоки могут содержать как описания, так и исполняемые операторы.
условно исключения различных версий заголовочного файла:
#ifdef VERSION == 1
#define INCLFILE “vers_1.h”
#elif VERSION == 2
#define INCLFILE “vers_2.h”
#else
#define INCLFILE “vers_N.h”
#endif
#include INCFILE

Слайд 44

Директивы препроцессора

В константных выражениях может использоваться проверка, определена ли константа с помощью

Директивы препроцессора В константных выражениях может использоваться проверка, определена ли константа с
директивы difine, например:
#if defined(__BORLANDC__) &&
__BORLAND__ ==0530 // BC5.3
typedef istream_iterator istream_it;
#else
typedef istream_iterator istream_iter;

Слайд 45

Директивы препроцессора

И еще одно применение директив условной трансляции – временное комментирование фрагмента

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

Слайд 46

Предопределенные макросы

Например, макрос __splusplus определен, если программа компилируется в среде С++.
#ifdef __cplusplus
cout

Предопределенные макросы Например, макрос __splusplus определен, если программа компилируется в среде С++.
<< " C++ " << endl;
#else cout << " no C++ " << endl;
#endif
Это макрос использовался в период перехода от С к С++.

Слайд 47

Предопределенные макросы

Другие макросы:
- __DATE__ - содержит строку с текущей датой (месяц, день,

Предопределенные макросы Другие макросы: - __DATE__ - содержит строку с текущей датой
год), например,
cout << __DATE__ << endl;
- __FILE__ - содержит строку с полным именем текущего файла, например,
cout << __FILE__ << endl;

Слайд 48

Предопределенные макросы

- __LINE__ - текущая строка исходного текста;
- __TIME__ - текущее время.

Предопределенные макросы - __LINE__ - текущая строка исходного текста; - __TIME__ - текущее время.

Слайд 49

Предопределенные макросы

Предопределенные макросы
Имя файла: Модульное-программирование.-Шаблоны-функций.pptx
Количество просмотров: 68
Количество скачиваний: 1