вернуться в оглавление предыдущая глава предыдущий параграф следующий параграф следующая глава


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

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

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

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

функции, выполняющие одинаковые действия для разных типов:

перегруженные функции:

 print_double(double d);
 print_Lens(Lens l);
 print_2(double x, double y); 
 void print(double d);
 void print(Lens l);
 void print(double x, double y); 

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

  1. Проверка точного соответствия типов аргументов функции и передаваемых параметров
  2. Попытка “повышения типов” (short -> int, flot -> double и т.д.)
  3. Попытка стандартных преобразований (int -> double, double -> int, указатели -> void* и т.д.)
  4. Преобразование, явно задаваемое программистом

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

float sqrt(float); 
float sqrt(double); 
double sqrt(double); 

6.1.2. Преобразование типов

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

  1. bool, char повышается до int
  2. int < long < flot < double. Операнд более низкого типа повышается до более высокого.

Явное преобразование типов:

  1. (тип) выражение - ( int) x;
  2. тип (выражение) – int (x);

Для классов для преобразования типов используется конструктор с одним параметром:

// преобразование из double в Complex
Complex::Complex(double x) 
{
    m_re=x; 
    m_im=0.;
}
// пример использования
Complex x;
x=Complex(3.14); 

Однако для некоторых типов данных использование конструктора для преобразования типа не имеет смысла и может приводить к нежелательным последствиям. Оператор explicit запрещает неявный вызов конструктора для преобразования типа:

// оператор explicit запрещает неявный вызов конструктора для преобразования типа
class Matrix
{
public:
    explicit Matrix(int size);
}
Matrix::Matrix(int size)
{
    m_data=new double[size*size];
}

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.