Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Перегрузка функций. Лабораторная работа №12. Перегрузка функций






Лабораторная работа №12. Перегрузка функций. Шаблоны функций

Цель и порядок работы

Цель работы – ознакомиться с возможностью перегрузки функций и научиться применять полученные знания на практике. Научиться использовать шаблоны функции и функции с переменным количеством параметров.

 

Порядок выполнения работы:

- ознакомиться с описанием лабораторной работы;

- получить задание у преподавателя, согласно своему варианту;

- написать программу и отладить ее на ЭВМ;

- оформить отчет.

Краткая теория

Каждая программа на C++ – это совокупностьфункций, каждая из которых должна быть определена или описана до её использования в конкретном модуле программы. Рассмотрим более сложные примеры использования функций.

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

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

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

Небольшие перегруженные функции удобно применять при отладке программ.

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

 

void print(char *str, const int i, const int j)

{

cout < < str < < '|' < < oct < < setw(4) < < i < < '|' < < setw(4) < < j

< < '|' < < endl;

}

 

void print(float array[], const int n)

{

cout < < " Массив: " < < endl;

cout.setf(ios:: fixed);

cout.precision(2);

for (int i = 0; i < n; i++)

{

cout < < array[i] < < " ";

if ((i + 1) % 4 == 0) cout < < endl;

}

cout < < endl;

}

 

void print(Man m)

{

cout.setf(ios:: fixed);

cout.precision(2);

cout < < setw(40) < < m.name < < ' ' < < m.birthday < < ' '

< < m.pay < < endl;

}

 

В первой из этих функций на экран выводятся строка и два целых числа в восьмеричной форме, разделенных вертикальными черточками для читаемости. Под каждое число отводится по 4 позиции (действие манипулятора setw распространяется только на ближайшее выводимое поле).

Во второй функции для вывода вещественных значений по четыре числа на строке задается вид вывода с фиксированной точкой и точностью в два десятичных знака после запятой. Для этого используются методы установки флагов setf, установки точности precision и константа fixed, определенная в классе ios. Точность касается только вещественных чисел, ее действие продолжается до следующей установки. Третья функция выводит поля знакомой нам по шестому семинару структуры так, чтобы они не склеивались между собой. Манипулятор setw устанавливает ширину следующего за ним поля. Это приведет к тому, что фамилии будут выведены с отступом от края экрана. Вызов этих функций в программе может выглядеть, например, так:

 

print(" После цикла ", i, j);

print(a, n);

print(m);

 

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

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

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

Неоднозначность может также возникнуть из-за параметров по умолчанию и ссылок. Рассмотрим создание перегруженных функций на примере.

 

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

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

 

#include " stdafx.h"

#include < iostream>

#include < math.h>

 

using namespace std;

 

//объявим две структуры для хранения информации о координатах точек

//в декартовой системе

struct cartesian{

double x, y;

};

 

//и в по системе координат

struct polar{

double r, pi;

};

 

//теперь определим перегружаемую функцию,

//принимающую координаты двух точек через полярные координаты

double len(polar a, polar b)

{

cout < < " Считаем расстояние через полярные координаты" < < endl;

return sqrt(pow(a.r, 2) + pow(b.r, 2) - 2*a.r*b.r*cos(a.pi - b.pi));

}

//а затем принимающую координаты двух точек через декартовы координаты

double len(cartesian x, cartesian y)

{

cout < < " Считаем расстояние через декартовы координаты" < < endl;

return sqrt(pow(y.x - x.x, 2)+pow(y.y - x.y, 2));

}

//будем считать, что при передаче четырех параметров

//передаются декартовы координаты двух точек

double len(double x1, double y1, double x2, double y2)

{

cout < < " Считаем расстояние через декартовы \

координаты с 4-мя параметрами" < < endl;

return sqrt(pow(x2 - x1, 2)+pow(y2 - y1, 2));

}

 

void main(int argc, char* argv[])

{

setlocale(LC_ALL, " Russian");

 

const double PI = 3.14159;

 

cartesian a = {3, 0},

b = {1, 1};

 

polar c = {1.41, PI/4},

d = {3.1, 0.95};

 

double x1 = 1.4, y1 = 2.5,

x2 = 2.1, y2 = 3.7;

 

cout < < len(a, b) < < endl;

cout < < len(c, d) < < endl;

cout < < len(x1, y1, x2, y2) < < endl;

}

 

Результат работы:

 

Считаем расстояние через декартовы координаты

2.23607

Считаем расстояние через полярные координаты

1.7246

Считаем расстояние через декартовы координаты с 4-мя параметрами

1.38924

 






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.