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

6.1.3. Параметры функций по умолчанию

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

// описание полного конструктора с параметрами по умолчанию

Lens(double r1, double r2, double D=0., double d=0., double n=1.);

// реализация полного конструктора с параметрами по умолчанию

Lens::Lens(double r1, double r2, double D, double d, double n)

: m_r1(r1)

, m_r2(r2)

, m_d(d)

, m_D(D)

, m_n(n)

{

}

При вызове такого конструктора можно указывать набор параметров от 2 до 5, при этом отсутствующие параметры будут инициализированы параметрами по умолчанию. Обратите внимание, что отсутствующие параметры всегда должны быть в конце перечисления.

Lens lens1(100., -100.); // в результате: r1=100., r2=-100., D=0., d=0., n=1.

Lens lens1(100., -100., 50.); // в результате: r1=100., r2=-100., D=50., d=0., n=1.

Lens lens1(100., -100., 50., 10.); // в результате: r1=100., r2=-100., D=50., d=10., n=1.

Lens lens1(100., -100., 50., 10., 1.5); // в результате: r1=100., r2=-100., D=0., d=10., n=1.5

Lens lens1(100., -100., 1.5); // в результате: r1=100., r2=-100., D=1.5, d=0., n=1.

6.2. Перегрузка операторов

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

Например, для комплексных чисел (типа данных Complex) можно перегрузить следующие операторы:

  • * – комплексное умножение

  • + – комплексное сложение

  • ~ – комплексное сопряжение

Complex x,y,z;

z=x*y;

z=x.operator*(y); // явный вызов оператора

class Complex

{

Complex operator*(const Complex& other) const;

}

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

Рассмотрим пример класса Complex, а затем разберем подробно перегрузку некоторых типовых операторов.

6.2.1. Пример 6.1 (класс Complex (комплексное число))

/////////////////////////////////////////////////////////////////////////////

// Прикладное программирование

// Пример 6.1. Класс Комплексное число

// complex.h

//

// Кафедра Прикладной и компьютерной оптики, http://aco.ifmo.ru

// СПб НИУ ИТМО

/////////////////////////////////////////////////////////////////////////////

// проверка на повторное подключение файла

#if !defined COMPLEX_H

#define COMPLEX_H

#include <iostream>

using namespace std;

/////////////////////////////////////////////////////////////////////////////

// класс Комплексное число

class Complex

{

private:

// вещественная и мнимая часть комплексного числа

double m_re, m_im;

public:

// конструкторы

Complex();

Complex(double re, double im=0);

Complex(const Complex& other);

// получение параметров комплексного числа

double GetRe() const;

double GetIm() const;

// изменение параметров комплексного числа

void Set(double re, double im=0.);

// оператор умножения

Complex operator*(const Complex& other) const;

// оператор умножения на число

Complex operator*(const double& other) const;

// оператор умножения с присваиванием

Complex& operator*=(const Complex& other);

// оператор присваивания

Complex& operator=(const Complex& other);

// оператор равенства

bool operator== (const Complex& other) const;

// оператор сопряжения комплексного числа

Complex operator~() const;

// унарный минус

Complex operator-() const;

// ввод/вывод комплексного числа

friend ostream& operator<< (ostream& out, const Complex& x);

friend istream& operator>> (istream& out, Complex& x);

// преобразование типа Complex в double

operator double() const;

};

/////////////////////////////////////////////////////////////////////////////

// получение вещественной части комплексного числа

inline double Complex::GetRe() const

{

return m_re;

}

/////////////////////////////////////////////////////////////////////////////

// получение мнимой части комплексного числа

inline double Complex::GetIm() const

{

return m_im;

}

/////////////////////////////////////////////////////////////////////////////

// изменение параметров комплексного числа

inline void Complex::Set(double re, double im)

{

m_re=re;

m_im=im;

}

/////////////////////////////////////////////////////////////////////////////

#endif //defined COMPLEX_H

 

/////////////////////////////////////////////////////////////////////////////

// Прикладное программирование

// Пример 6.1. Класс Комплексное число

// complex.cpp

//

// Кафедра Прикладной и компьютерной оптики, http://aco.ifmo.ru

// СПб НИУ ИТМО

/////////////////////////////////////////////////////////////////////////////

// подключение описания класса

#include "complex.h"

/////////////////////////////////////////////////////////////////////////////

// конструктор по умолчанию

Complex::Complex()

: m_re(0.)

, m_im(0.)

{

}

/////////////////////////////////////////////////////////////////////////////

// полный конструктор

Complex::Complex(double re, double im)

: m_re(re)

, m_im(im)

{

}

/////////////////////////////////////////////////////////////////////////////

// конструктор копирования

Complex::Complex(const Complex& x)

: m_re(x.m_re)

, m_im(x.m_im)

{

}

/////////////////////////////////////////////////////////////////////////////

// оператор умножения

Complex Complex::operator*(const Complex& other) const

{

return Complex(m_re*other.m_re-m_im*other.m_im,

m_re*other.m_im-m_im*other.m_re);

}

/////////////////////////////////////////////////////////////////////////////

// оператор умножения на число

Complex Complex::operator*(const double& other) const

{

return Complex(m_re*other, m_im*other);

}

/////////////////////////////////////////////////////////////////////////////

// оператор умножения с присваиванием

Complex& Complex::operator*=(const Complex& other)

{

Complex temp(*this);

m_re=temp.m_re*other.m_re - temp.m_im*other.m_im;

m_im=temp.m_re*other.m_im + temp.m_im*other.m_re;

return (*this);

}

/////////////////////////////////////////////////////////////////////////////

// унарный минус

Complex Complex::operator-() const

{

return Complex(-m_re, -m_im);

}

/////////////////////////////////////////////////////////////////////////////

// оператор сопряжения комплексного числа

Complex Complex::operator~() const

{

return Complex(m_re, -m_im);

}

/////////////////////////////////////////////////////////////////////////////

// оператор равенства

bool Complex::operator== (const Complex& other) const

{

return (m_re == other.m_re && m_im == other.m_im);

}

/////////////////////////////////////////////////////////////////////////////

// оператор присваивания

Complex& Complex::operator=(const Complex& other)

{

if(this != &other)

{

m_re=other.m_re;

m_im=other.m_im;

}

return *this;

}

/////////////////////////////////////////////////////////////////////////////

// преобразование типа Complex в double

Complex::operator double() const

{

return (m_re*m_re-m_im*m_im);

}

/////////////////////////////////////////////////////////////////////////////

// вывод комплексного числа на экран

ostream& operator<< (ostream& out, const Complex& x)

{

return (out<<"("<<x.m_re<<","<<x.m_im<<")");

}

/////////////////////////////////////////////////////////////////////////////

// ввод комплексного числа с клавиатуры

istream& operator>> (istream& in, Complex& x)

{

return (in>>x.m_re>>x.m_im);

}

/////////////////////////////////////////////////////////////////////////////

 

/////////////////////////////////////////////////////////////////////////////

// Прикладное программирование

// Пример 6.1. Класс Комплексное число

// test_complex.cpp

//

// Кафедра Прикладной и компьютерной оптики, http://aco.ifmo.ru

// СПб НИУ ИТМО

/////////////////////////////////////////////////////////////////////////////

#include <iostream>

using namespace std;

// подключение описания класса

#include "complex.h"

/////////////////////////////////////////////////////////////////////////////

// пример использования класса Complex

void main()

{

Complex x(1,1), y(2,2), res1, res2, res3;

Complex x1;

// тестирование преобразования типов

// преобразование вещественного числа в комплексное при помощи конструктора

res1=Complex(3.14);

cout<<"Complex(3.14): "<<res1<<endl;

// преобразование комплекcного числа в вещественное при помощи перегруженного оператора double

double c=double(res1);

cout<<"double(res1): "<<c<<endl<<endl;

// тестирование арифметических операторов

res1=x*y; // перемножение двух комплексных чисел

res1=x.operator*(y); // то же самое, явный вызов оператора

res2=-x; // унарный минус

res3=~x; // комлексное сопряжение

x*=y; // умножение с присваиванием

cout<<" x*y="<<res1<<endl;

cout<<" -x="<<res2<<endl;

cout<<" ~x="<<res3<<endl;

cout<<"x*=y: "<<x<<endl<<endl;

// тестирование оператора равенства

if(x==y)

cout<<x<<" = "<<y<<endl<<endl;

else

cout<<x<<" != "<<y<<endl<<endl;

// тестирование операторов присваивания

res3=res2=res1=1;

cout<<res1<<"="<<res2<<"="<<res3<<endl;

}

/////////////////////////////////////////////////////////////////////////////

6.2.2. Перегрузка бинарных операторов

// оператор умножения

Complex Complex::operator*(const Complex& other) const

{

return Complex(m_re*other.m_re-m_im*other.m_im,

m_re*other.m_im-m_im*other.m_re);

}

// оператор умножения на число

Complex Complex::operator*(const double& other) const

{

return Complex(m_re*other, m_im*other);

}

// пример использования

Complex x, z;

double y;

z=x*y;

6.2.3. Перегрузка унарных операторов

// унарный минус

Complex Complex::operator-() const

{

return Complex(-m_re, -m_im);

}

// оператор сопряжения комплексного числа

Complex Complex::operator~() const

{

return Complex(m_re, -m_im);

}

// пример использования

Complex x, y;

y=-x;

y=~x;

6.2.4. Перегрузка логических операторов

// оператор равенства

bool Complex::operator== (const Complex& other) const

{

return (m_re == other.m_re && m_im == other.m_im);

}

// пример использования

Complex x, y;

if(x==y)

{

}

6.2.5. Перегрузка оператора присваивания

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

  1. Аргументом перегруженного оператора присваивания должна быть неизменяемая ссылка на экземпляр данного класса (чтобы случайно не испортить экземпляр).

  2. Перед осуществлением присваивания необходимо осуществить проверку на присваивание самому себе (чтобы не выполнять лишних действий).

  3. Оператор должен осуществлять поэлементное присваивание (то есть должно быть выполнено последовательное присваивание каждой переменной).

  4. Оператор должен возвращать ссылку на самого себя (чтобы оно было похоже на присваивание встроенных типов данных, тогда будет возможна запись x=y=z=1).

// оператор присваивания

Complex& Complex::operator=(const Complex& other)

{

if(this != &other)

{

m_re=other.m_re;

m_im=other.m_im;

}

return *this;

}

// пример использования

Complex x, y, z;

x=y=z=1;