2013 10 29_cpp_lecture_07
Upcoming SlideShare
Loading in...5
×
 

2013 10 29_cpp_lecture_07

on

  • 1,803 views

 

Statistics

Views

Total Views
1,803
Views on SlideShare
249
Embed Views
1,554

Actions

Likes
0
Downloads
10
Comments
0

3 Embeds 1,554

http://beta.compscicenter.ru 1540
http://compscicenter.ru 13
http://gamma.compscicenter.ru 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

2013 10 29_cpp_lecture_07 2013 10 29_cpp_lecture_07 Presentation Transcript

  • Лекция 7. Namespace. Переопределение операторов Valery Lesin. C++ Basics, 2013 1
  • namespace • • • • 1. 2. 3. 4. 5. 6. 7. 8. 9. Задает именованное пространство имен Позволяет избежать конфликты имен Может быть вложенным В отличие от классов, может расширяться namespace std { void sort(/*...*/){/*...*/} } namespace std { void for_each(/*...*/){/*...*/} } Valery Lesin. C++ Basics, 2013 2
  • Объявление и использование namespace’ов. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. namespace std { void sort(/*...*/); } namespace std { void sort(/*...*/) {/*...*/} } // or even better(why?): void std::sort(/*...*/){/*...*/} // usage: void foo() { int a [10] = {1, 2, 3, 4, /*...*/}; std::sort(a, a + 10); } Valery Lesin. C++ Basics, 2013 3 View slide
  • using директива • Можно раскрыть пространство имен: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. namespace std { void sort(/*...*/); struct vector{/*...*/}; } void process() { using namespace std; vector v; sort(v.begin(), v.end()); } Valery Lesin. C++ Basics, 2013 4 View slide
  • using объявление • А можно вносить лишь то, что нужно: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. void process() { using std::sort; using std::vector; vector v; sort(v.begin(), v.end()); } /////////////////////////////////////////////////////////////////// /////// // operations like on sets namespace A { void foo(); /*...*/ } namespace B { void foo(); /*...*/ } namespace C { using namespace A; using namespace B; using A::foo(); } Valery Lesin. C++ Basics, 2013 5
  • Поиск Кёнига (ADL) • Позволяет найти функцию в пространстве имен одного из ее аргументов (крайне полезно для операторов). 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. namespace long_numbers { struct lint{/*...*/}; lint& operator+=(lint&, int); } void process() { // --- 1 --std::vector v; // don't need to write std::sort sort(v.begin(), v.end()); // --- 2 --long_numbers::lint i; i+= 5; //without Argument dependent name lookup: long_numbers::operator+=(i, 5); } Valery Lesin. C++ Basics, 2013 6
  • Перегрузка операторов • Традиционный интерфейс для объектов из предметной области, особенно математики • Сохраняйте естественную семантику. Для класса rectangle::operator+(int) может увеличить его размер, а может покомпонентно сдвинуть – здесь лучше именованная функция. • Если есть a @= b, то программисты ожидают и a@b и b@a. Valery Lesin. C++ Basics, 2013 7
  • Что можно и нельзя? • Можно перегружать почти все операторы (кроме :: ; .* ; , ; ?:) • Нельзя определить новую лексему оператора. Например a**b вместо pow(a, b). Может это a*(*b)? • Нельзя изменить приоритет. Если point::operator^ - векторное умножение, то p1 ^ p2 + p3 это p1 ^ (p2 + p3) Valery Lesin. C++ Basics, 2013 8
  • Что можно и нельзя? (part 2) • Если есть a@b и a=b, то само a@=b не появится. Аналогично наличие оператора a==b не сделает a!=b. Поможет boost::operators • Нельзя изменить количество операндов • Нельзя переопределить операторы, в которых участвуют только встроенные типы Valery Lesin. C++ Basics, 2013 9
  • Где и как писать операторы? • Объявление оператора начинается со слова operator • Можно вызвать как обычную функцию • Можно объявлять как member, свободную или дружественную функцию 1. 2. 3. 4. 5. 6. T T::operator+(T const& other); //... T a, b; a + b; a.operator+(b); Valery Lesin. C++ Basics, 2013 10
  • Примеры объявления операторов 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. struct lint { lint& operator++(); lint operator++(int); lint& operator+=(lint const&); lint operator+ (lint const&); int operator[](size_t index) const; }; // or lint& operator++(lint&); lint operator++(lint&, int); lint& operator+=(lint&, lint const&); lint operator+ (lint const&, lint const&); int operator[](const lint&, size_t index); // error! Valery Lesin. C++ Basics, 2013 11
  • Оператор a@b через a@=b 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. struct string { string& operator+=(const char*); }; string operator+(string, const char*); ///////////////////////////////////////////////////////////////// string& string::operator+=(const char* str) { //impl ... return *this; } string operator+(string lhs, const char* rhs) { return lhs += rhs; } // or even better string operator+(string const& lhs, const char* rhs) { string tmp; tmp.reserve(lhs.size() + strlen(rhs)); return (tmp += lhs) += rhs; } Valery Lesin. C++ Basics, 2013 12
  • Предопределенный смысл операторов • У операторов =; &; , есть предопределенный смысл. Но и их можно переопределить или даже закрыть 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. struct file { // impl ... private: file(file const&); file& operator=(file const&); }; // file a(/*...*/), b(/*...*/); a = b; // error! Valery Lesin. C++ Basics, 2013 13
  • Явное и неявное преобразование 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. struct my_int { explicit my_int(int); operator int(); }; struct my_double { my_double(double); explicit operator double(); // C++11 }; void foo(my_int const&); void bar(double); // foo(5); // error bar(double(my_double(5.))); // ok // never mix implicit constructor and operator // my_int + my_int // or // int + int ? my_int(5) + 6; // error, ambiguous Valery Lesin. C++ Basics, 2013 14
  • Смешанная арифметика • Есть string s, хотим иметь возможность писать s < "a", "a" < s, s < s. Как? 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. // way 1 (lazy): string::string(const char*); // implicit operator<(string const&, string const&); // way 2 (optimal): bool less(const char*, const char*); operator<(string const& lhs, const char* rhs) { less(lhs.c_str(), rhs); } operator<(const char*lhs, string const& rhs) { less(lhs, rhs.c_str()); } operator<(string const&, string const&); { less(lhs.c_str(), rhs.c_str()); } Valery Lesin. C++ Basics, 2013 15
  • Friend функции • Member-функции: 1. Доступ к private 2. В области видимости класса 3. Имеют неявный this • static – 1 и 2 • friend – только 1 • friend должны быть объявлены прежде в обрамляющей класс области видимости или иметь параметр класса • Объявлять можно и в public и в private • Можно сделать friend целиком класс (все его функции) Valery Lesin. C++ Basics, 2013 16
  • Пример friend operator’a 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. struct lint { friend std::ostream& operator<< (std::ostream& os, lint const& i); private: std::vector<int> data_; }; std::ostream& operator<<(std::ostream& os, lint const& i) { //impl... return os; } Valery Lesin. C++ Basics, 2013 17
  • Префиксный и постфиксный инкремент 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. struct iterator { // impl... iterator& operator++(); private: T* ptr_; }; iterator& iterator::operator++() { ++ptr_; return *this; } iterator operator++(iterator& it, int) { iterator tmp(it); ++it; return tmp; } Valery Lesin. C++ Basics, 2013 18
  • Функторы • Очень удобны для реализации callback’ов и visitor’ов 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. struct rotation { rotation(double angle); void operator()(point& p); private: double angle_; }; void rot_points(vector<point>& vec, double a) { for_each(vec.begin(), vec.end(), rotation(a)); } Valery Lesin. C++ Basics, 2013 19
  • Операторы для указателя 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. template<class T> struct smart_ptr { T* operator->() { return ptr_; } T& operator[](size_t i) { return ptr_[i];} T& operator* () { return *ptr_; } private: T* ptr_; }; struct X {void foo();}; int main() { smart_ptr<X> px; px->foo(); return 0; } Valery Lesin. C++ Basics, 2013 20
  • Какими делать функции? • Если функция – один из операторов =; ->; []; () делаем их членами (нет выбора) • Иначе – если 1. функция требует левый аргумент иного типа (<<) 2. требует преобразования типа для левого аргумента, 3. можно реализовать только через открытый интерфейс класса(!), – делайте ее не членом класса (возможно, в (1) и (2) – друзьями) • Иначе, сделайте ее функцией-членом. Valery Lesin. C++ Basics, 2013 21
  • Вопросы? Valery Lesin. C++ Basics, 2013 22