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

Полиморфизм

Адаптеры очереди

Очереди и стек

Двусторонняя очередь (дека)

deque - очень похожа на vector: так же как и vector, она является последовательностью, которая поддерживает произвольный доступ к элементам. Главное что отличает deque от vector - это то, что deque также поддерживает вставку и удаление в начало последовательности за постоянное время. Кроме того, deque не имеет функций-членов аналогичных функциям-членам vector capacity() и reserve(), и не предоставляет никаких гарантий на допустимость итератора, который ассоциирован с его функциями-членами.

deque разновидность очереди - очереди с двумя концами имеет методы очереди и вектора

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

deque<int> Q;
Q.push_back(3);
Q.push_front(1);
Q.insert(Q.begin() + 1, 2);
Q[2] = 0;
copy(Q.begin(), Q.end(), ostream_iterator<int>(cout, " "));
// Значения, которые будут напечатаны, это 1 2 0

Стек и очередь имеют методы с одинаковыми именами, но они имеют разное смысловое значение:

queue stack

stack -- это адаптер очереди, который организует ее работу по особому правилу: "last in -- first out" (LIFO). Элемент, который был добавлен последним (push) будет извлечен первым (pop). stack не предоставлет функция для получения итераторов и их перебора. Можно лишь проверить, какой элемент находится на вершине стека (top). Например:

int main()
{
stack<int> S;
S.push(8);
S.push(7);
S.push(4);
...
S.pop();
S.pop();
S.pop();
}

queue -- это адаптер очереди, который организует ее работу по особому правилу: "first in first out" (FIFO). Элемент, который был добавлен последним (push) будет извлечен последним (pop). queue не предоставлет функция для получения итераторов и их перебора. Можно лишь проверить, какой элемент стоит в очереди первым (front). Например:

int main()
{
queue<int> Q;
Q.push(8);
Q.push(7);
Q.push(6);
Q.push(2);
Q.pop();
Q.pop();
Q.pop();
Q.pop();
}

Полимрфизм - возможность принимать множество форм, иметь разный смысл в зависимости от ситуации.

Полиморфизм в языке С++ позволяет программисту:

  1. Создавать функции имеющие одинаковые имена, но разные наборы аргументов (по количеству и по типу данных) - перегрузка функций
  2. Определять действие операторов для новых АТД - перегрузка операторов

Таким образом, в зависимости от набора аргументов и их типов будет вызываться та или иная функция, хотя они имеют одинаковые имена. А при работе с АТД программист не будет испытывать неудобств, он будет использовать операторы + для сложения или объединения двух объектов, а оператор = для присвоения одного экземпляра объекта другому.

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

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

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. Преобразование явно задаваемые программистом

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

print_int(int i);
print_char(char c);
print_Lens(Lens l);

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

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

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

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

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

  1. (тип) выражение
  2. тип (выражение) - функциональная запись

Для АТД (для class) конструктор с одним параметром используется для преобразования типов.

complex::complex(double x) // преобразование из double в complex
{
m_re=x; m_im=0.;
}

complex x;
x=complex(1.);

Но это не всегда удобно и может приводить к нежелательным последствиям:

Matrix::Matrix(int size)
{
m_data=new double[size*size];
m_rows=size;
m_cols=size;
}

class Matrix
{
public:
explicit Matrix(int size);
}

explicit запрещает неявный вызов конструктора для преобразования типа.

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

complex::complex(double re, double im=0.)
{
m_re=re; m_im=im;
}

complex x(1.0,0.0);
complex y(1.0); // то же самое

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


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: