Студопедия

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

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

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






Краткие теоретические сведения. Перегрузка функций. В Си++ реализован механизм перегрузки






 

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

сlass fraction{…

void mult(int a); // умножение дроби на целое число

void mult(fraction a); // умножение дроби на дробь

}

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

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

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

тип_возвращаемого_значения operator знак_операции (параметры_операции){тело_функции-операции }

Когда оператор функция – член класса перегружает унарный оператор у нее не будет параметров. Когда перегружается бинарный оператор, у функции будет один параметр. Этот параметр получит тот объект, который будет расположен справа от знака оператора. Объект слева генерирует вызов оператор-функции и передается неявно с помощью указателя this.

Создадим класс для работы с комплексными числами и переопределим для него операцию +.

class complex{

int Re, Im;

public: void input(); //ввод комплексного числа

void output(); //вывод комплексного числа

complex operator+(complex ob2); //переопределяем оператор +

};

void complex:: input(){//ввод

cout< < " Input Re"; cin> > Re;

cout< < " Input Im"; cin> > Im;

}

void complex:: output(){//вывод

cout< < Re< < " +i" < < Im;

}

complex complex:: operator +(complex ob2){

complex temp; // переменная для результата сложения чисел

temp.Re=Re+ob2.Re; // складываем действительные части

temp.Im=Im+ob2.Im; // складываем мнимые части

return temp; // возвращаем результат

}

В качестве параметра функция получает переменную типа complex под названием ob2. Это число, которое стоит справа от знака +. Re и Im это внутренние переменные числа, которое стоит справа от знака +. Т.е. функция выполняет сложение двух чисел Re+iIm и ob2.Re+iob2.Im. Если тип параметра ob2 будет, например, int, то эта функция будет вызываться, когда складывается справа от знака + комплексное, а слева целое число. Тип возвращаемого значения complex, так как в результате сложения двух комплексных чисел получается комплексное число.

void main(){

complex A, B, C; //объявляем три переменные типа complex

A.input(); //ввод числа A

B.input(); //ввод числа B

C=A+B; //сложение двух комплексных чисел

C.output(); //вывод результата

}

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

1. Дружественная функция может быть определена внутри самого класса, однако это самостоятельная функция, которая имеет право доступа к частным (private) и защищённым (protected) членам класса.

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

Пример. Пусть у нас имеется земельный участок, на котором необходимо с трех сторон установить забор из заборных блоков. Необходимо определить, сколько заборных блоков нужно купить. Для решения задачи создадим два класса: ground для работы с участком и blockFence для работы с заборным блоком. Нам необходимо создать функцию, которая исходя из размеров участка будет вычислять количество необходимых заборных блоков. Т.е. наша функция должна иметь доступ одновременно к свойствам двух классов. Чтобы не объявлять эти свойства открытыми, можно пойти другим путем и объявить функцию как дружественную.

class blockFence; //предварительное объявление

class ground{//класс участок

int length, width; //размеры участка

public: ground (int l, int w){ length=l; width=w; }; //конструктор

//объявляем дружественную функцию

friend countBlockFence(ground g, blockFence b);

};

class blockFence {//заборный блок

int width; //ширина

public: blockFence (int w){ width =w; }; //конструктор

// объявляем дружественную функцию

friend countBlockFence(ground g, blockFence b);

};

int countBlockFence(ground g, blockFence b){/*возвращает количество заборных блоков для ограждения участка с трех сторон*/

return (g.length+2*g.width)/b. width;

}

void main(){

ground g(100, 30); //участок размером 100 на 30 метров

blockFence b1(2); //заборный блок размером 10 метров

cout< < " Вам потребуется " < < countBlockFence(g, b1)< < " блоков";

}

Пользовательская функция ввода не может быть членом класса, для которого она создана. Если оператор функция является членом класса, то левый операнд является объектом, генерирующим вызов оператор функции. Т.е. левый операнд должен быть объектом этого класса. Однако в случае операторов ввода/вывода левый операнд – это поток, а правый – объект, который нужно вывести. Как и в предыдущем примере, оператор функцию можно сделать дружественной.

Модифицируем класс комплексных чисел, заменив функции input() и output() функциями, переопределяющими стандартные операторы ввода/вывода.

class complex{

int Re, Im;

public: complex operator+(complex ob2); //переопределяем оператор +

friend ostream & operator< < (ostream & stream, complex ob); //переопределяем оператор вывода

friend istream & operator> > (istream & stream, complex & ob); //переопределяем оператор ввода

};

ostream & operator< < (ostream & stream, complex ob){

stream< < ob.Re< < " +i" < < ob.Im;

return stream;

};

istream & operator> > (istream & stream, complex & ob){

cout< < endl< < " Input Re"; cin> > ob.Re;

cout< < " Input Im"; cin> > ob.Im;

return stream;

}

void main(){

complex A, B, C;

cin> > A> > B; //ввод чисел

C=A+B; //сложение

cout< < A< < " +" < < B< < " =" < < C; //вывод результата

}

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

 






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