Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ООП 1-3 лекции.docx
Скачиваний:
5
Добавлен:
18.11.2019
Размер:
55.63 Кб
Скачать
    1. Перегрузка функций

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

Примеры:

void f(int);

void f(char);

void f(long);

void f(float, int);

void f(int, int, int);

Функции с параметрами, заданными по умолчанию - пример перегрузки функций. Важно! перегружаемые функции не должны иметь совпадающие списки параметров (в том числе и при использовании параметров по умолчанию).

Вместе с приведенными выше примерами не может быть задана функция

void f(long, float = 0, char = '*');

но можно задать такую функцию:

void f(float, long = 0, char = '*');

    1. Перегрузка операций

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

Правила перегрузки операций:

  • могут быть перегружены только предопределенные операции;

  • могут быть перегружены почти все (унарные и бинарные) операции;

  • унарный/бинарный характер операции не может быть изменен: это означает, что приоритет операции, правило ассоциативности и количество операндов изменить нельзя!

  • перегруженная операция должна содержать по крайней мере один аргумент типа класса.

Перегрузка бинарных операций: прототип перегруженной операции имеет вид:

тип_возвращаемого_значения operator binaryOp(тип_параметра параметр1);

Перегруженная операция может быть использована в выражении как явный (op1.operator binaryOp op2) или неявный (op1 binaryOp op2) вызов функции-операции и интерпретируется так: op1 получает сообщение binaryOp с аргументом op2.

Пример перегрузки бинарной операции (сложение для класса Rational):

class Rational{

public:

...

Rational operator +(Rational r);

...

}

Rational Rational::operator +(Rational r)

{

Rational tmp;

tmp.num = num*r.den + den*r.num;

tmp.den = den*r.den;

tmp.reduce();

return tmp;

}

Использование перегруженной операции:

Rational a(1,4), b(1,3), c;

c = a + b; // c = a.operator +(b);

Унарные операции перегружаются аналогично, за исключением ++ и —- (они могут иметь префиксную и постфиксную формы записи):

Префиксная ++ (или --):

Rational operator ++();

Реализация операции ++:

Rational Rational::operator ++()

{

num += den;

return *this;

}

Постфиксная ++ (или --):

Rational operator ++(int);

Реализация операции ++:

Rational Rational::operator ++()

{

Rational tmp = *this;

num += den;

return tmp;

}

Использование перегруженных операций:

Rational a(1,5);

a++; // эквивалентно a.operator ++(int);

++a; //эквивалентно a.operator ++();

    1. Выбор функции

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

Правила сравнения:

  1. Точные совпадения

  2. Расширения

  3. Стандартные преобразования

  4. Преобразования, требующие временные переменные

  5. Преобразования, определенные пользователем

Точные совпадения: совсем не используются преобразования.

Расширения: предполагают преобразования, при котором увеличивается длина аргумента, но не изменяется его внутреннее представление (например, char в int).

Стандартные преобразования: предполагают изменение внутреннего представления аргумента (например, int в float).

Преобразования, требующие временные переменные: выполняются, если параметр объявлен как ссылка, а аргумент требует преобразования типа (например, преобразование из float в int&) или задан выражением, значение которого не может быть изменено.

Преобразования, определенные пользователем: будут рассмотрены позднее.

Примеры:

void print(int);

void print(const char *);

void print(double);

void print(long);

void print(char);

char c; int i; short s; float f;

print(c); // правило 1; вызывается print(char)

print(i); // правило 1; вызывается print(int)

print(s); // правило 2; вызывается print(int)

print(f); // правило 2; вызывается print(double)

print('a'); // правило 1; вызывается print(char)

print(49); // правило 1; вызывается print(int)

print("a"); // правило 1; вызывается print(const char *)

Пример с ошибками:

void f(int, float);

void f(float, int);

Вызов, который приведет к генерации сообщения об ошибке (неоднозначный выбор):

f(1.5, 1.5);