Задачи на 28 апреля
DESCRIPTION
Задачи на 28 апреля. Язык С++. 1. Задача 3: swp. template void swp(T& x, T& y) { T tmp = x; x = y; y = tmp; } Замечание: T tmp ; // Так хуже, чем T tmp = x; tmp = x; - Немного медленнее - PowerPoint PPT PresentationTRANSCRIPT
Задачи на 28 апреля
Язык С++ 1
Задача 3: swptemplate <class T>void swp(T& x, T& y){
T tmp = x;x = y;y = tmp;
}
Замечание:T tmp; // Так хуже, чем T tmp = x;tmp = x;
- Немного медленнее - Более существенно, работает только если в классе есть
конструктор по умолчанию (определение менее общее).Язык С++ 2
Задача 1: Удаление кружка - планOnRButtonDown Ищем кружок, в который мы попали Если нашли, то удаляем Перерисовываем
Язык С++ 3
Задача 1: Удаление кружкаvoid CCirclesView::OnRButtonDown(UINT nFlags, CPoint point) { vector<CPoint>::iterator p; for (p=m_circles.begin(); p != m_circles.end(); p++) { if ( (p->x - pt.x)*(p->x - pt.x) + (p->y - pt.y)*(p->y - pt.y) <= 100 ) { // Попали в круг? m_circles.erase(p); Invalidate(); break; // Больше не ищем } } CView::OnRButtonDown(nFlags, point);}
Перерисовать лучше только если куда-то попали Кстати: тут после erase пользоваться p нельзя!
Язык С++ 4
Архитектура "Документ/представл
ение" (Document-View)
Язык С++ 5
Тут мы обсуждали, почему лучше иметь два класса – один для данных, и другой для их изображения
Архитектура Document-View Данные хранятся не в окне, а в отдельном классе
(C…Doc, производный от CDocument) Взаимодействие:
Из окна можно получить указатель на документ:pDoc = GetDocument();
Можно обновить окно для документа (или окна, их может быть несколько):UpdateAllViews(NULL);
Почему удобно использовать такую архитектуру? Несколько окон для одного документа Несколько способов просмотра Вообще часто полезно разделять объект и его изображение
Примерно то же: MVC (model-view-controler).
Язык С++ 7
Circles в архитектуре Document-View m_circles - перенести в CCirclesDoc
class CCirclesDoc { vector<CPoint> m_circles;
OnDraw:CCirclesDoc* pDoc= GetDocument();for (int i = 0; i < pDoc->m_circles.size(); i++) { CPoint& pt = pDoc->m_circles[i]; pDC->Ellipse(pt.x – 10, pt.y – 10, pt.x + 10, pt.y + 10, }
OnLButtonDown:CCirclesDoc* pDoc= GetDocument();pDoc->m_circles.push_back(point);pDoc->UpdateAllViews(NULL);
Язык С++ 8
Шаблоны классов
Язык С++ 9
Пример: шаблон класса "стек"template <class T>class stack { T stk[100]; int size;
public: stack() : size(0) {}
void push(const T& x) {
size[top++] = x; }
T pop {
return stk[--size]; }};
Использование
stack<int> s1;stack<double> s2;stack<complex> s3;stack<stack<int>> s4;
При использовании параметры надо указывать явно
Язык С++ 10
Замечания Методы можно описывать вне класса
template <class T> void stack<T>::push(const T& x){ ...}
В частности, конструктор:
template <class T>stack<T>::stack(): size(0){}
Язык С++ 11
Еще возможности Не типовые параметры:
template <class T, int maxsize>class stack {
T stk[maxsize]; …};
stack<int, 100> s;
Такие параметры м.б. только целые (и в некоторых случаях указатели)
При вызове д.б. константы Внутри - как константы
Параметры по умолчанию
template <class T, int maxsize = 100>class stack { …
stack<int> s;// To же, что stack<int, 100>
Язык С++ 12
typename Пусть в разных классах
определен один вложенный тип.
class a {typedef int mytype;…
};
class b {typedef double mytype;…
};
class c {typedef bool mytype;…
};
И мы пишем шаблон, в котором используем это.
template <classT>void f(T x){
… T::mytype x; …
}
Проблема: Откуда компилятор знает, что T::mytype это тип (а не поле T или метод T и т.д.)?
Приходится подсказывать..
Язык С++ 13
typename - продолжениеtemplate <class T>void f(T x){
… typename T::mytype y; …
}
typename относится к выражению T::mytype Означает: "мы обещаем, что при вызове это будет вложенный в
T тип"
Язык С++ 14
Специализация Специализация шаблона
template <>class stack<char*> {
// Что-то особенное};
Специализация метода
template <>void stack<double>:: push(double x) {
// Что-то особенное}; Реальный пример из STL – vector<bool>
Язык С++ 15
Частичная специализацияtemplate <class T>class stack<T*> {
// Что-то особенное};
М.б. сложная система разных специализаций
template <class T1, class T2>class abc { … };
template <class T>class abc<T, T> { … };
template <class T>class abc<T, int> { … };
template <class T>class abc<T*, T> { … };
template <class T1, class T2>class abc<T1*, T2*> { … };
Не во всех компиляторах! (Visual C++ после VS 2003)
Язык С++ 16
Шаблон методаclass abc {
…template <class T> void f(T x) { … }…
};abc x;x.f(5); // f<int>x.f(3.14); // f<double>
// Примерtemplate <class T>class complex {
T re, im;…
template <class T1>complex(const T1& from) :
re(from.re), im(from.im){}
};
// Хотим задать преобразование// complex -> complexcomplex<int> c1(1,2);complex<double> c2 = c1;
Генерируется конструктор complex<double>
(const complex<int>& from)Язык С++ 17
Параметры - шаблоны Не будет на экзамене
template < template<class > class T >class abc {
T<int> x;T<double> y;T<double> z;…
};
abc<stack> v;
Язык С++ 18
Замечания Пишем код, который работает для разных типов.
Называется: полиморфизм Статический полиморфизм
По-моему опыту: Не старайтесь использовать сложные возможности шаблонов Легко запутаться
Язык С++ 19
Еще об итераторах и контейнерах
value_type T::value_type – тип того, что содержится в контейнере
Например, если T – это list<int>, то T::value_type – это int
И тоже для итераторов
Если T – это list<int>::iterator, то T::value_type – это int
Используется, в основном, в шаблонах
Тут мы разбирали простой пример использования: шаблон функции, которая возвращает первый элемент любого последовательного контейнера. И обсудили типичные ошибки.
Разделяемые данные
(В частности, разделяемая память и когда ее удалять)
Язык С++ 22
Несколько указателей на один объект в динамической памятиВспомним проблемы при копировании string: Меняем одну строку – меняются все
Ну, допустим, мы не меняем строки (immutable objects)
Оставшиеся проблемы одним предложением: “непонятно, когда удалять” Один из вариантов решения –
счетчик указателей При объекте храним количество указателей, которые на него
указывают Тогда можем сказать, когда можно удалить (когда счетчик
уменьшился до 0)
Язык С++ 23
Строки с разделяемым содержимым// Пример:shared_string s1 = “abc”;shared_string s2 = “klm”;
s2 = s1; // “klm” освобождается. На “abc” – 2 указателя.
shared_string s3 = “pqr”;s1 = s3; // На “abc” – 1 указатель.s2 = s3; // “abc” удаляется
Где хранить счетчик? Мы не можем хранить в классе shared_string, его тоже надо
разделять для нескольких shared_string Вариант (м.б. не лучший) – в первом байте строки. Но
возможны и другие решенияЯзык С++ 24
Программы из нескольких исходных
файлов
Язык С++ 25
Программа из нескольких файлов -1 Схема
a.cppb.cpp
компилируем...а.objb.obj
linker …a.exe (или a.dll)
Как определить что-то в одном файле, а использовать в другом?
a.cppvoid f(int i){ …}
b.cpp… f(56); …// f надо объявить
Программа из нескольких файлов -2a.cpp
void f(int i){ …}
b.cppvoid f(int i);
...… f(56); …
// ОК, так все работает, но:// обычно так не делают!
Почему? Неудобно, особенно если
файлов много При изменениях надо
много где исправлять Легко забыть исправить.
Программа из нескольких файлов – обычно пишут так: Директива include:
#include <имя_файла>смысл: включить в это место текст из файла
a.cppvoid f(int i){ …}
a.h void f(int i);
b.cpp#include “a.h”
...… f(56); …
с.cpp#include “a.h”
...… f(42); …
В a.h – все, что другие должны знать о a.cpp (все необходимые объявления)
Как добавить в проект новые файлы? Пусть мы хотим добавить в проект новый cpp файл. В Visual
Studio это делается так: В меню выберите Project + Add New Item… В форме выберите в списке «С++ File (.cpp)» и в поле Name
введите имя файла.
Чтобы добавить новый h файл надо сделать то же самое, но в списке выбрать «Header File (.h)»
Если не будет получаться – пишите, я подскажу.
Задачи на 5 мая
Язык С++ 30
Задачи на 5 мая - 11. «Разные фигурки»
Написать программу типа Circles, которая позволяет задавать картинки из каких-нибудь трех видов фигур (например, кружки, квадраты и ромбы). Д.б. возможность добавлять и
удалять. Перемещение можно не реализовывать.
Как выбирать фигуру для добавления? Один вариант: в меню выбираeм "текущую фигуру". О работе с меню будет документ на сайте.
За эту задачу 2 балла – один за добавление и один за удаление.
2. Опишите шаблон функции, которая для любого последовательного контейнера (списка, вектора, deque) ищет сумму входящих в него положительных элементов.
Замечание: шаблон должен работать не только для контейнеров из целых чисел, но и для вещественных, rational и т.д.
(Продолжение на следующем слайде)
Язык С++ 31
Задачи на 5 мая – 2 3. Шаблон fixed_queue - очередь
фиксированной длины (аналог stack, но first in – first out).
// Пример использованмяqueue<int, 100> q;q.push(3); q.push(7); q.push(11);cout << q.pop(); // 3cout << q.pop(); // 7
4. Реализовать shared_stringНадо реализовать: конструктордеструктор, оператор=, конструкторкопирования, метод print.
При этом строчки не должныникогда реально копироваться.
Надо только переставлятьуказатели, подсчитывать ихколичество, и удалять строки, накоторые уже никто не указывает.
За эту задачу тоже можнозаработать два балла. Одинбалл для тех, кто напишет что-топохожее на правильное решение,и второй балл за совсем правильноерешение.
(Окончание на следующем слайде)
Язык С++ 32
Задачи на 5 мая – 35. Написать функцию, которая дляцелого числа проверяет,совершенное оно или нет, ивозвращает true или false.
Справка: число называется совершенным, если оно равно суммесвоих делителей. Например: 28 = 1+2+4+7+14
Что для такой функции д.б.написано в cpp файле, и что в hфайле?
Дополнительное пожелание:Желательно, чтобы функцияработала по возможности быстро.