2013 12 03_cpp_lecture_11
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads

Views

Total Views
1,058
On Slideshare
351
From Embeds
707
Number of Embeds
3

Actions

Shares
Downloads
8
Comments
0
Likes
0

Embeds 707

http://beta.compscicenter.ru 683
http://compscicenter.ru 23
http://gamma.compscicenter.ru 1

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Лекция 11. Введение в шаблоны. Часть 2. Специализация. Связь с наследованием. Умные указатели Valery Lesin. C++ Basics, 2013 1
  • 2. Шаблонный класс 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. template<class T> struct vector { vector(size_t count = 0, T def = T()); vector(vector const& other); // don't need to write vector<T> inside vector& operator=(vector const& other); void resize(size_t size); void clear (); T& operator[](size_t index); T const& operator[](size_t index) const; size_t size() const; private: T* size_t }; data_; size_; Valery Lesin. C++ Basics, 2013 2
  • 3. Специализация шаблонов класса • Можно указать особую реализацию класса для выбранного типа • Такая специализация не обязана иметь тот же интерфейс, что и общий шаблон (хотя это обычно ожидается пользователями) 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. template<class T> struct vector { /* impl */ }; template<> struct vector<bool> { /* compact storage for bool array e.g. in bits */ }; Valery Lesin. C++ Basics, 2013 3
  • 4. Частичная специализация • Допустима только для классов. Функции требуют полной специализации. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. template<class T, class A> struct vector { /* impl */ }; template<class A> struct vector<bool, A> { /* compact storage for bool array e.g. in bits */ }; Valery Lesin. C++ Basics, 2013 4
  • 5. Общая нешаблонная база • Позволяет значительно сэкономить на кодогенерации. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. template<class T> struct vector<T*> : private vector<void*> { typedef vector<void*> base_t; typedef T* value_type; explicit vector(size_t size, value_type def = value_type()) : base_t(size, def) {} T& at(size_t index) { return static_cast<value_type>(base_t::at(index)); } T& operator[](size_t index) { return at(index); } }; Valery Lesin. C++ Basics, 2013 5
  • 6. Явное инстанцирование • Позволяет избежать многократного инстанцирования одного и того же шаблона 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. //******** string.h ******************/ /* a little more complex in real STL */ template<class char_t> class basic_string{/*...*/}; typedef basic_string<char> string; // prevent of instantiation extern template class basic_string<char>; //******* some.cpp or lib ************/ // explicit instantiation template class basic_string<char>; Valery Lesin. C++ Basics, 2013 6
  • 7. Специализация шаблонов функций • Допускается только полная специализация. Но и она-то редко нужна. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. template<class T> void swap(T& x, T& y) { T tmp = x; x = y; y = tmp; } template<> void swap<my_class>(my_class&, my_class&) { /* effective implementation */ }; Valery Lesin. C++ Basics, 2013 7
  • 8. Специализация шаблонов функций • Допускается только полная специализация. Но и она-то редко нужна – если передается параметр типа, хватит перегрузки. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. // overriding void swap(my_class&, my_class&) { /* effective implementation */ }; template<class T> void swap(vector<T>& x, vector<T>& y) { using std::swap; //for all the functions named swap(!) swap(x.data_, y.data_); swap(x.size_, y.size_); }; Valery Lesin. C++ Basics, 2013 8
  • 9. Curiously recurring template pattern (CRTP) 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. template<class derived_t> struct comparable { bool operator==(derived_t const&) const; bool operator!=(derived_t const&) const; bool operator>=(derived_t const& rhs) const { rhs < derived(); } private: derived_t& derived() {return static_cast<derived_t&>(*this);} derived_t const& derived() const {return static_cast<derived_t const&>(*this);} }; struct point : comparable<point> { bool operator<(point const& rhs) const; /**/}; //------------------point x(...), y(...); bool check = x != y; Valery Lesin. C++ Basics, 2013 9
  • 10. Наследование и шаблоны • Шаблоны от динамически полиморфных типов не связаны между собой 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. struct base {/**/}; struct derived : base {/**/}; // vector<base> vb; vector<derived> vd; vb = vd; // error // but vector<base*> vpb; vpb.push_back(new derived); Valery Lesin. C++ Basics, 2013 10
  • 11. Шаблонные функции в нешаблонном классе 1. struct any 2. { template<class T> 3. any(T const& obj); 4. 5. 6. any(any const& other); 7. /*....*/ 8. 9. }; • Такие функции не могут быть виртуальными • Но! Шаблонный класс может реализовывать абстрактный интерфейс • Осторожно: шаблонный конструктор не замещает генерируемый Valery Lesin. C++ Basics, 2013 11
  • 12. Как связать шаблоны класса, если связаны его параметры? 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. template<class T> struct shared_ptr { shared_ptr() : ptr_(nullptr), count_(0){} shared_ptr(shared_ptr const&){/**/} template<class U> shared_ptr(shared_ptr<U> const& other) : ptr_ (other.get()) , count_(other.count_) { ++(*count_); } /*a little more complex in real life*/ /*....*/ T* get() const { return ptr_; } private: T* ptr_; size_t* count_; }; //--------------------------shared_ptr<derived> pd; shared_ptr<base> pb(pd); Valery Lesin. C++ Basics, 2013 12
  • 13. Динамический vs Статический полиморфизм • Один и тот же код используется для в действительности разных типов • Может использоваться для типов, неизвестных на момент написания кода • Динамический: – Единообразная работа, основанная на отношении надмножество/подмножество – Динамическое связывание и раздельная компиляция – Необходима бинарная согласованность (ABI) Valery Lesin. C++ Basics, 2013 13
  • 14. Динамический vs Статический полиморфизм • Статический: – Единообразная работа, основанная на синтактическом и семантическом интерфейсе – Статическое связывание. Мешает раздельной компиляции – Высокая эффективность (такая же, как и специальный код для типа) Valery Lesin. C++ Basics, 2013 14
  • 15. Пара слов про exceptions 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. struct my_exception : std::runtime_error { my_exception(const char* my_description) : std::runtime_error(my_description) {} }; try { /*...*/ if (bad_condition) throw my_exception("bad_condition"); } catch (std::exception const& err) // (!) only ref { std::cerr << err.what(); } Valery Lesin. C++ Basics, 2013 15
  • 16. Умные указатели • Почти те же указатели, только умнее – представляют собой RAII классы – поддерживают тот же интерфейс, что и обычные указатели: op->, op*, op< (например, чтобы положить в std::set) – сами управляют временем жизни объекта – вовремя вызывают деструкторы и освобождают память Valery Lesin. C++ Basics, 2013 16
  • 17. Польза умных указателей • Автоматическое освобождение памяти при удалении самого указателя • Безопасность исключений 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. void foo() { shared_ptr<my_class> ptr(new my_class("arg")); // or shorter definition: auto ptr = make_shared<my_class>("arg"); ptr->bar(); // if throws exception, nothing bad happened } void foo() { my_class* ptr = new my_class(/*...*/); ptr->bar(); // oops, troubles in case of exception delete ptr; // common trouble is to forget delete } Valery Lesin. C++ Basics, 2013 17
  • 18. Популярные умные указатели • std :: scoped_ptr • std :: unique_ptr • std :: shared_ptr • std :: weak_ptr • boost :: intrusive_ptr • Deprecated: std :: auto_ptr Valery Lesin. C++ Basics, 2013 18
  • 19. scoped_ptr • Удобен для хранения указателя на стеке или полем класса. Не позволяет копироваться. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. template<class T> struct scoped_ptr : noncopyable { public: typedef T element_type; explicit scoped_ptr(T * p = 0); ~scoped_ptr(); void reset(T * p = 0); T & operator *() const; T * operator->() const; T * get() const; operator unspecified-bool-type() const; }; //------scoped_ptr<int> p(new int(5)); Valery Lesin. C++ Basics, 2013 19
  • 20. Почему explicit конструктор? 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. //what if scoped_ptr had implicit constructor void foo(scoped_ptr<my_class> ptr) { /*...*/ } auto p = new my_class(/*...*/); foo(p); // epic fail, p is not valid after this call p->do_smth();// error delete p; // one more error Valery Lesin. C++ Basics, 2013 20
  • 21. shared_ptr • Поддерживает общий счетчик ссылок на выделенный объект • Удаляет объект только, когда последний из ссылающихся shared_ptr’ов удаляется или принимает указатель на другой объект Valery Lesin. C++ Basics, 2013 21
  • 22. shared_ptr • • • • Наиболее используемый. Удобен для разделения владением. Можно возвращать из функций. *Можно передавать между модулями - запоминает правильную функцию удаления (из нужной библиотеки) 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. template<class T> struct shared_ptr { /* more than scoped_ptr has */ shared_ptr(shared_ptr const & r); template<class Y> shared_ptr(shared_ptr<Y> const & r); shared_ptr(shared_ptr && r); template<class Y> shared_ptr(shared_ptr<Y> && r); bool unique() const; long use_count() const; /*...*/ }; Valery Lesin. C++ Basics, 2013 22
  • 23. Вопросы? Valery Lesin. C++ Basics, 2013 23