2013 10 29_cpp_lecture_07

22
Лекция 7. Namespace. Переопределение операторов Valery Lesin. C++ Basics, 2013 1

description

 

Transcript of 2013 10 29_cpp_lecture_07

Page 1: 2013 10 29_cpp_lecture_07

Лекция 7. Namespace.

Переопределение операторов

Valery Lesin. C++ Basics, 2013 1

Page 2: 2013 10 29_cpp_lecture_07

namespace

• Задает именованное пространство имен

• Позволяет избежать конфликты имен

• Может быть вложенным

• В отличие от классов, может расширяться

Valery Lesin. C++ Basics, 2013 2

1.

2.

3.

4.

5.

6.

7.

8.

9.

namespace std

{

void sort(/*...*/){/*...*/}

}

namespace std

{

void for_each(/*...*/){/*...*/}

}

Page 3: 2013 10 29_cpp_lecture_07

Объявление и использование

namespace’ов.

Valery Lesin. C++ Basics, 2013 3

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);

}

Page 4: 2013 10 29_cpp_lecture_07

using директива

• Можно раскрыть пространство имен:

Valery Lesin. C++ Basics, 2013 4

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());

}

Page 5: 2013 10 29_cpp_lecture_07

using объявление

• А можно вносить лишь то, что нужно:

Valery Lesin. C++ Basics, 2013 5

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();

}

Page 6: 2013 10 29_cpp_lecture_07

Поиск Кёнига (ADL)• Позволяет найти функцию в пространстве имен

одного из ее аргументов (крайне полезно для операторов).

Valery Lesin. C++ Basics, 2013 6

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);

}

Page 7: 2013 10 29_cpp_lecture_07

Перегрузка операторов

• Традиционный интерфейс для объектов из предметной области, особенно математики

• Сохраняйте естественную семантику. Для класса rectangle::operator+(int) может увеличить его размер, а может покомпонентно сдвинуть – здесь лучше именованная функция.

• Если есть a @= b, то программисты ожидают и a@b и b@a.

Valery Lesin. C++ Basics, 2013 7

Page 8: 2013 10 29_cpp_lecture_07

Что можно и нельзя?

• Можно перегружать почти все операторы

(кроме :: ; .* ; , ; ?:)

• Нельзя определить новую лексему

оператора. Например a**b вместо pow(a,

b). Может это a*(*b)?

• Нельзя изменить приоритет. Если

point::operator^ - векторное умножение,

то p1 ^ p2 + p3 это p1 ^ (p2 + p3)

Valery Lesin. C++ Basics, 2013 8

Page 9: 2013 10 29_cpp_lecture_07

Что можно и нельзя? (part 2)

• Если есть a@b и a=b, то само a@=b не

появится. Аналогично наличие оператора

a==b не сделает a!=b. Поможет

boost::operators

• Нельзя изменить количество операндов

• Нельзя переопределить операторы, в

которых участвуют только встроенные типы

Valery Lesin. C++ Basics, 2013 9

Page 10: 2013 10 29_cpp_lecture_07

Где и как писать операторы?

• Объявление оператора начинается со слова operator

• Можно вызвать как обычную функцию

• Можно объявлять как member, свободную или дружественную функцию

Valery Lesin. C++ Basics, 2013 10

1.

2.

3.

4.

5.

6.

T T::operator+(T const& other);

//...

T a, b;

a + b;

a.operator+(b);

Page 11: 2013 10 29_cpp_lecture_07

Примеры объявления операторов

Valery Lesin. C++ Basics, 2013 11

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!

Page 12: 2013 10 29_cpp_lecture_07

Оператор a@b через a@=b

Valery Lesin. C++ Basics, 2013 12

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;

}

Page 13: 2013 10 29_cpp_lecture_07

Предопределенный смысл операторов

• У операторов =; &; , есть

предопределенный смысл. Но и их можно

переопределить или даже закрыть

Valery Lesin. C++ Basics, 2013 13

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!

Page 14: 2013 10 29_cpp_lecture_07

Явное и неявное преобразование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

Page 15: 2013 10 29_cpp_lecture_07

Смешанная арифметика• Есть string s, хотим иметь возможность

писать s < "a", "a" < s, s < s. Как?

Valery Lesin. C++ Basics, 2013 15

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()); }

Page 16: 2013 10 29_cpp_lecture_07

Friend функции

• Member-функции:

1. Доступ к private

2. В области видимости класса

3. Имеют неявный this

• static – 1 и 2

• friend – только 1

• friend должны быть объявлены прежде в обрамляющей класс области видимости или иметь параметр класса

• Объявлять можно и в public и в private

• Можно сделать friend целиком класс (все его функции)

Valery Lesin. C++ Basics, 2013 16

Page 17: 2013 10 29_cpp_lecture_07

Пример friend operator’a

Valery Lesin. C++ Basics, 2013 17

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;

}

Page 18: 2013 10 29_cpp_lecture_07

Префиксный и постфиксный инкремент

Valery Lesin. C++ Basics, 2013 18

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;

}

Page 19: 2013 10 29_cpp_lecture_07

Функторы

• Очень удобны для реализации callback’ов и visitor’ов

Valery Lesin. C++ Basics, 2013 19

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));

}

Page 20: 2013 10 29_cpp_lecture_07

Операторы для указателя

Valery Lesin. C++ Basics, 2013 20

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;

}

Page 21: 2013 10 29_cpp_lecture_07

Какими делать функции?

• Если функция – один из операторов =; ->; []; () делаем их членами (нет выбора)

• Иначе

– если

1. функция требует левый аргумент иного типа (<<)

2. требует преобразования типа для левого аргумента,

3. можно реализовать только через открытый интерфейс класса(!),

– делайте ее не членом класса (возможно, в (1) и (2) – друзьями)

• Иначе, сделайте ее функцией-членом.

Valery Lesin. C++ Basics, 2013 21

Page 22: 2013 10 29_cpp_lecture_07

Вопросы?

Valery Lesin. C++ Basics, 2013 22