Слайд 1Преобразования типов
В языке C/C++ имеется несколько операций преобразования типов. Они используются
в случае, если переменная одного типа должна рассматриваться как переменная другого типа.
Преобразование типов потенциально может привести к возникновению ошибок. Его использование не рекомендуется.
Слайд 2Приведение типов
в стиле C
Операция может записываться в двух формах:
тип(выражение)
или (тип) выражение.
Например
float c = double(1)/7;
float d = (double)1/7;
Приведение типов чаще всего используется для преобразования нетипизированного указателя (на void) в типизированный.
Например функция сравнения строк для сортировки выглядит так:
int cmp (const void *a, const void *b)
{ return strcmp( (const char *) a,
(const char *) b);
}
Слайд 3Операция const_cast
Используется для удаления модификатора const. Обычно используется для передачи константного
указателя в функцию в качестве параметра, соответствующего обычному указателю. const_cast <тип> выражение.
void print (int *p)
{ cout << *p; }
int main()
{ int t = 10;
const int *p = &t;
print (const_cast (p));
}
Слайд 4Операция static_cast
Используется вместо приведения типов C, а также для преобразования между
указателями и ссылками на объекты одной иерархии.
static_cast <тип> выражение;
float d =static_cast(1)/7;
Слайд 5Пример преобразования типов в иерархии классов
class dog : public animal
{ public:
…
void guard() { say(); cout<< "rrrrrrr..." <};
int main()
{ animal * f = new dog ("filya");
f->say(); f->hungry(); // f->guard();
static_cast (f)->guard();
// static_cast (c)->guard();
return 0;
}
Возможно также обратное преобразование из указателя (или ссылки) на производный класс в базовый. Недостаток статического преобразования - отсутствует контроль за правильностью применения преобразования
Слайд 6Операция dynamic_cast
Выполняет преобразование между классами одной иерархии. Результат преобразования может быть
проверен. Если объект не может быть преобразован к указанному типу, то возвращается нулевая ссылка.
int main()
{ animal * f = new dog ("filya");
animal * c = new cat ("murka");
dog * d = dynamic_cast (f);
if (d) d->guard(); else cout <<"error";
dog * e = dynamic_cast (c);
if (e) e->guard(); else cout <<"error";
return 0;
}
Слайд 7Динамическое определение типа
В С++ определена операция typeid, которая возвращает ссылку на
объект класса type_info.
У класса type_info есть метод name() – имя типа. Для объектов класса type_info определено сравнение на равенство и неравенство.
cout << typeid (*f). name() <
Слайд 8Шаблоны функций
Многие алгоритмы не зависят от типов данных, с которыми работают.
Например, вычисление максимального элемента или сортировка. В этом случае можно написать несколько перегруженных функций, но в таком случае один и тот же код придется много раз писать.
int max (int a, int b)
{ if (a>b) return a;
else return b;
}
В С++ можно описать шаблон – семейство функций, которые зависят от типа данных. Конкретный тип данных передается в виде параметра на этапе компиляции. Компилятор автоматически создает код, соответствующий переданному типу.
Слайд 9Описание шаблона функции
template
заголовок
{ // тело функции
}
Может быть
несколько параметров, как типов, так и переменных.
Слайд 10Пример использования шаблона
template
T max (T a, T
b)
{ if (a>b) return a;
else return b;
}
int main()
{ int a=10, b = 5;
double c = 3, d = 10;
cout << max(a,b) < cout << max(c,d) <// cout << max(a,d) < cout << max(a,d) < return 0;
}
Слайд 11Обработка шаблона
Первый вызов функции приводит к созданию компилятором кода для версии
функции соответствующего типа. Этот процесс называется инстанцирование шаблона. Тип инстанцирования либо определяется автоматически исходя из типов параметров, либо задается явно.
Слайд 12Шаблоны классов
В С++ можно использовать шаблоны классов
template
class
имя_класса
{ // поля и методы используют аргумент тип
};
Слайд 13Пример: стек данных произвольных типов
#include
template
Max = 1000>
class stack {
private:
Data st[Max];
int top;
public:
stack (): top(0) {}
void push(Data x)
{ st[top++] = x; }
Data pop()
{ return st[--top]; }
bool empty()
{ return (top == 0);}
};
int main()
{ stack <> s1;
s1.push('a'); s1.push('b'); s1.push('c');
cout << "1: " << s1.pop() << endl;
cout << "2: " << s1.pop() << endl;
cout << "3: " << s1.pop() << endl;
stack s2;
s2.push(1); s2.push(2); s2.push(3);
while (! s2.empty())
cout << s2.pop() << endl;
return 0;
}
Слайд 14Использование шаблонов классов
Классы инстанцируются при описании объектов.
Шаблоны методов не могут
быть виртуальными.
Если для определенного типа существует более эффективный код, то можно использовать специализацию шаблона.