Слайд 2
Использование const
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени П.А.Овчинникова
Что
такое const и зачем его использовать?
Есть две точки зрения
на использование const:
Первая: const - это плохо.
Вторая: const - это хорошо.
Чем отличаются?
int *const p1;
int const* p2;
const int* p3;
Слайд 3
Константы и методы
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени
П.А.Овчинникова
Для методов допустимо использование const, применительно к this.
class A
{
private:
int x;
public:
void f(int a) const{
x = a; // <-- не работает
}
};
Слайд 4
Перегрузка операторов
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени П.А.Овчинникова
Рассмотрим
бинарный оператор @, если х имеет тип X, а
у имеет тип Y, правила разрешения выражения х@у применяются следующим образом:
если X является классом, выяснить, определяется ли operator@ в качестве члена класса Х, либо базового класса Х;
если X определен в пространстве имен N, поискать объявления operator@ в N;
если У определен в пространстве имен М, поискать объявления operator@ в М.
Слайд 5
Операторы-члены и не-члены
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени
П.А.Овчинникова
Рекомендуется сводить к минимуму количество функций, непосредственно манипулирующих представлением
объекта.
Старайтесь определять в теле самого класса только те операторы, которые должны модифицировать значение первого аргумента, например оператор +=.
Операторы, которые просто выдают новое значение на основе своих аргументов, такие как +, рекомендуется определять вне класса
Слайд 6
Операторы-члены и не-члены
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени
П.А.Овчинникова
class complex {
double re, im;
public:
complex(double
r, double i);
complex& operator+=(complex a); // требует доступа к представлению
};
complex operator+(complex a, complex b)
{
complex r = a;
return r += b; // доступ к представлению при помощи +=
}
inline complex& complex::operator+=(complex a)
{
re += a.re;
im += a.im;
return *this;
}
Слайд 7
Операторы-члены и не-члены
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени
П.А.Овчинникова
void f(complex x, complex y, complex z)
{
complex rl =
x + y + z;
complex r2 = x;
r2 += y,
r2 += z;
complex d = 2 + b;
}
// rl = operator+(operator+(x,y), z)
// r2 = x
// r2.operator+= (y)
// r2.operator+=(z)
// Ошибка!!! Нет operator+(2,b)
Скомпилируется программа?
Все ли хорошо работает?
Слайд 8
Операторы-члены и не-члены
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени
П.А.Овчинникова
complex& complex::operator+=(double a){
re += a;
return *this;
}
complex operator+(complex a, complex
b){
complex r = a;
return r+= b; // вызывает complex: :operator+= (complex)
}
complex operator+(complex a, double b){
complex r = a;
return r += b; // вызывает complex::operator+=(double)
}
complex operator+ (double a, complex b){
complex r = b;
return r += a; // вызывает complex::operator+= (double)
}
Слайд 9
Операторы-члены и не-члены
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени
П.А.Овчинникова
void f(complex x, complex y)
{
complex rl = x +
y;
complex r2 = x + 2;
complex r3 = 2 + x;
}
Слайд 10
Конструктор инициализатор
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени П.А.Овчинникова
class
complex {
double re, im;
public:
complex(double r, double i);
};
class test_class {
const
int n;
complex e;
complex& t;
public:
test_class();
};
У класса complex есть конструктор по умолчанию?
В чем проблема(ы) класса test_class?
Как инициализировать значения полей?
Слайд 11
Конструктор инициализатор
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени П.А.Овчинникова
class
test_class {
const int n;
complex e;
complex& t;
public:
test_class(int _n=0, complex _e=complex(0,0),
complex& _t=complex(0,0));
};
test_class::test_class(int _n,complex _e,complex& _t):n(_n),e(_e),t(_t){}
Слайд 12
Инициализация
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени П.А.Овчинникова
Для инициализации
и присваивания комплексным переменным скалярных значений, нам нужно преобразование
скалярной величины
complex b = 3;
class complex {
double re, im;
public:
complex(double r) : re(r), im(0) {}
// ...
};
Слайд 13
Конструкторы и преобразования
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени
П.А.Овчинникова
complex(double r) : re(r), im(0) {}
Конструктор является предписанием для
создания значения данного типа из типа double.
Конструктор используется, когда ожидается значение данного типа, и когда такое значение может быть создано конструктором из значения, заданного как инициализатор, или присваиваемого значения. Поэтому, конструктор, имеющий один аргумент, не нужно вызывать явно.
Например,
complex b = 3;
complex b = complex(3);
Слайд 14
Конструкторы и преобразования
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени
П.А.Овчинникова
Мы определили три варианта каждой из четырех стандартных арифметических
операций:
complex operator+ (complex, complex);
complex operator+ (complex, double);
complex operator+ (double, complex);
Слайд 15
Конструкторы и преобразования
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени
П.А.Овчинникова
Альтернативным способом реализации различных версий функции для каждой комбинации
аргументов является использование преобразований типов.
class complex {
double re, im;
public:
complex(double r) : re(r), im(0) {}
// ...
};
complex operator+(complex a, complex b);
int main()
{
complex a = complex(1, 1);
complex b = 2+a;
return 0;
}
Слайд 16
Друзья класса
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени П.А.Овчинникова
Обычное
объявление функции-члена гарантирует три логически разные вещи:
функция имеет право
доступа к закрытой части объявления класса;
функция находится в области видимости класса;
функцию должна вызываться для объекта класса (имеется указатель this).
Слайд 17
Друзья класса
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени П.А.Овчинникова
Объявив
функцию-член как static какие свойства мы ей придаем?
Объявив функцию
как friend, мы наделяем ее только первым свойством.
Дружественная функция — это функция, которая не является членом класса, но имеет доступ к членам класса, объявленным в полях private или protected.
Слайд 18
Друзья класса
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени П.А.Овчинникова
Дружественные
функции
Дружественная функция объявляется внутри класса с модификатором friend
Дружественные
функции не являются членами класса, поэтому им не передается указатель this
Объявление функций-друзей friend можно поместить и в закрытой и в открытой частях объявления класса — не имеет значения, где именно.
Правило использования:
Если нет важных доводов использовать дружественные функции – используйте вместо них члены класса
Если важные доводы есть – подумайте, а действительно ли они так важны
Слайд 19
Друзья класса
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени П.А.Овчинникова
class
Matrix;
class Vector {
float v[4];
friend Vector
operator*(const Matrix&, const Vector&);
};
class Matrix {
float v[4][4];
friend Vector operator*(const Matrix&, const Vector&);
};
Vector operator*(const Matrix& matr, const Vector& vec){
Vector r;
for (int i = 0; i < 4; i++) {
r.v[i] = 0;
for (int j = 0; j < 4; j++)
r.v[i] += matr.v[i][j] * vec.v[j];
}
return r;
}
Слайд 20
Дополнительные функции-члены
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени П.А.Овчинникова
class
complex {
double re, im;
public:
complex(double
r = 0, double i = 0) :re(r), im(i) {};
complex& operator+= (complex);
complex& operator+= (double);
complex operator* (complex);
double real() const { return re;}
double imag() const { return im;}
};
inline bool operator== (complex a, complex b){
return (a.real() == b.real()) && (a.imag() == b.imag());
}
Слайд 21
Индексация
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени П.А.Овчинникова
int main()
{
string
buf;
Assoc_array vec;
while (cin >> buf) vec[buf]++;
vec.print_all();
return 0;
}
Слайд 22
Индексация
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени П.А.Овчинникова
Чтобы придать
смысл индексам для объектов класса можно воспользоваться функцией operator[].
Второй
аргумент (индекс) функции operator")] может быть любого типа.
Это делает возможным определение векторов, ассоциативных массивов и т. д.
Слайд 23
Индексация
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени П.А.Овчинникова
#include
#include
using namespace std;
struct Node{
string key;
double
val;
Node* next;
};
typedef Node* PNode;
class Assoc_array{
PNode Head=NULL;
PNode add(string key);
public:
Assoc_array() {}
double& operator[](const string&);
void print_all() const;
};
Слайд 24
Индексация
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени П.А.Овчинникова
PNode Assoc_array::add(string
key) {
PNode q = Head;
while (q && (q->key !=
key)) q = q->next;
if (!q)
{
PNode tmp = new Node;
tmp->key = key;
tmp->val = 0;
tmp->next = Head;
Head = tmp;
return tmp;
}
else return q;
}
Слайд 25
Индексация
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени П.А.Овчинникова
double& Assoc_array::operator[](const
string& key)
{
PNode q = Head;
while (q && (q->key !=
key)) q = q->next;
if (q) return q->val;
else return add(key)->val;
}
void Assoc_array::print_all() const
{
PNode q = Head;
while (q)
{
cout << "(" << q->key << "," << q->val << ")" << endl;
q = q->next;
}
}
Слайд 26
Индексация
Никитин Михаил Евгеньевич, 2015
ГБПОУ ПК имени П.А.Овчинникова
int main()
{
string
buf;
Assoc_array vec;
while (cin >> buf) vec[buf]++;
vec.print_all();
return 0;
}
Слайд 27
Пост- и пре- фиксные операторы?
Никитин Михаил Евгеньевич, 2015
ГБПОУ
ПК имени П.А.Овчинникова
По сравнению с другими операторами у этих
есть особенность - вы можете использовать их как в префиксной (++i, --i), так и в постфиксной (i++, i--) нотации.
Для того чтобы отличить постфиксную реализацию перегрузки от префиксной использует не используемый аргумент типа int.
Слайд 28
Пост- и пре- фиксные операторы?
Никитин Михаил Евгеньевич, 2015
ГБПОУ
ПК имени П.А.Овчинникова
class Point{
int _x, _y;
public:
Point& operator++();
// Prefix increment operator.
Point operator++(int); // Postfix increment operator.
Point& operator--(); // Prefix decrement operator.
Point operator--(int); // Postfix decrement operator.
Point() { _x = _y = 0; }
int x() { return _x; } // Define accessor functions.
int y() { return _y; } // Define accessor functions.
};
Слайд 29
Пост- и пре- фиксные операторы?
Никитин Михаил Евгеньевич, 2015
ГБПОУ
ПК имени П.А.Овчинникова
Point& Point::operator++() // Define prefix increment operator.
{
_x++;
_y++;
return
*this;
}
Point Point::operator++(int) // Define postfix increment operator.
{
Point temp = *this;
++*this;
return temp;
}