67.03K
Category: programmingprogramming

Анонимные объекты класса

1.

Анонимные объекты класса
class Dollars
{
private:
int m_dollars;
public:
Dollars(int dollars) { m_dollars = dollars; }
int getDollars() const { return m_dollars; }
};
Dollars add(const Dollars &d1, const Dollars &d2)
{
return Dollars(d1.getDollars() +d2.getDollars());
// возвращаем анонимный объект класса Dollars
}
int main()
{
Dollars dollars1(7);
Dollars dollars2(9);
std::cout << "I have " <<
add(dollars1, dollars2).getDollars()
<< " dollars." << std::endl;
// выводим анонимный объект
класса Dollars
return 0;
}

2.

Анонимные объекты рассматриваются как r-values (а не как l-values, у
которых есть адрес). Это означает, что анонимные объекты могут
передаваться
или
возвращаться
только
по
значению
или
по
константной ссылке. В противном случае должна использоваться
переменная.
Анонимные объекты можно использовать только один раз, так как они
имеют область видимости выражения.

3.

Перегрузка операторов
1. Почти любой существующий оператор в C++ может быть перегружен.
Исключениями являются:
Тернарный оператор (? :).
Оператор sizeof.
Оператор разрешения области видимости (::).
Оператор выбора члена (.).
2. Можно перегрузить только существующие операторы. Вы не можете создавать
новые или переименовывать существующие.
3. Только один из операндов перегруженного оператора должен быть
пользовательского типа данных.
4. Изначальное количество операндов, поддерживаемых оператором, изменить
невозможно.
5. Все операторы сохраняют свой приоритет и ассоциативность по умолчанию

4.

Правило: При перегрузке операторов старайтесь максимально
приближённо сохранять функционал операторов в соответствие с
их первоначальными применениями.
Есть три разных способа перегрузки операторов:
через дружественные функции;
через обычные функции;
через методы класса.

5.

Перегрузка операторов через дружественные функции
class Dollars
{
private:
int m_dollars;
public:
Dollars(int dollars) { m_dollars = dollars; }
// Выполняем Dollars + Dollars через дружественную функцию
friend Dollars operator+(const Dollars &d1, const Dollars &d2);
int getDollars() const { return m_dollars; }
};
Dollars operator+(const Dollars &d1, const Dollars &d2)
{
// Используем конструктор Dollars и operator+(int, int)
return Dollars(d1.m_dollars + d2.m_dollars);
}

6.

int main()
{
Dollars dollars1(7);
Dollars dollars2(9);
Dollars dollarsSum = dollars1 + dollars2;
std::cout << "I have " << dollarsSum.getDollars() << " dollars." << std::endl;
return 0;
}

7.

Перегрузка операторов с операндами разных типов
При перегрузке бинарных операторов для работы с операндами разных типов,
нужно писать две функции — по одной на каждый случай.
class Dollars
{ private:
int m_dollars;
public:
Dollars(int dollars) { m_dollars = dollars; }
friend Dollars operator+(const Dollars &d1, int value);
friend Dollars operator+(int value, const Dollars &d1);
int getDollars() { return m_dollars; }
};
Dollars operator+(const Dollars &d1, int value)
{
return Dollars(d1.m_dollars + value); }
Dollars operator+(int value, const Dollars &d1)
{
return Dollars(d1.m_dollars + value);
}

8.

Перегрузка операторов через обычные функции
Dollars.h:
class Dollars
{
private:
int m_dollars;
public:
Dollars(int dollars) { m_dollars = dollars; }
int getDollars() const { return m_dollars; }
};
Dollars operator+(const Dollars &d1, const Dollars &d2):
Dollars.cpp:
Dollars operator+(const Dollars &d1, const Dollars &d2)
{
return Dollars(d1.getDollars() + d2.getDollars());
}

9.

Перегрузка операторов ввода и вывода
class Point
{
private:
double m_x, m_y, m_z;
public:
Point(double x=0.0, double y=0.0, double z=0.0): m_x(x), m_y(y), m_z(z) {
double getX() { return m_x; }
double getY() { return m_y; }
double getZ() { return m_z; }
friend std::ostream& operator<< (std::ostream &out, const Point &point);
friend std::istream& operator>> (std::istream &in, Point &point);
};
}

10.

std::ostream& operator<< (std::ostream &out, const Point &point)
{
out << "Point(" << point.m_x << ", " << point.m_y << ", " << point.m_z << ")";
return out;
}
std::istream& operator>> (std::istream &in, Point &point)
{
in >> point.m_x;
in >> point.m_y;
void main()
in >> point.m_z;
{
return in;
std::cout << "Enter a point: \n";
}
Point point;
std::cin >> point;
std::cout << "You entered: " << point << '\n';
}

11.

Перегрузка операторов через методы класса
При перегрузке оператора через метод класса, левым операндом становится
неявный объект, на который указывает скрытый указатель this*.
class Dollars
{
private:
int m_dollars;
public:
Dollars(int dollars) { m_dollars = dollars; }
Dollars operator+(int value); // Выполняем Dollars + int
int getDollars() { return m_dollars; }
};
Dollars Dollars::operator+(int value)
{
return Dollars(m_dollars + value); }

12.

В перегрузке через метод класса выражение dollars1 + 3 приводит к
вызову dollars1.operator+(3).
dollars1 компилятор неявно конвертирует в скрытый левый параметр, на который
указывает указатель *this. Таким образом, dollars1.operator+(3) становится
вызовом operator+(&dollars1, 3)
Почему через метод класса перегрузить оператор << мы не сможем?

13.

Не всё может быть перегружено через дружественные функции
Операторы присваивания (=), индекса ([]), вызова функции (()) и выбора
члена (->) перегружаются через методы класса — это требование языка
C++.
Перегрузка операторов через методы класса не используется, если левый
операнд не является классом (например, int), или это класс, который мы
не можем изменить (например, std::ostream).

14.

Поэтому:
Для операторов присваивания (=), индекса ([]), вызова функции (())
или выбора члена (->) используйте перегрузку через методы класса.
Для унарных операторов используйте перегрузку через методы
класса.
Для перегрузки бинарных операторов, которые изменяют левый
операнд (например, operator+=) используйте перегрузку через методы
класса, если это возможно.
Для перегрузки бинарных операторов, которые не изменяют левый
операнд (например, operator+) используйте перегрузку через обычные
или дружественные функции.

15.

Задание
Контейнер map - это класс, в котором все элементы хранятся в виде пары
ключ-значение. Ключ должен быть уникальным и использоваться для
доступа к связанной паре. В этом задании вам нужно будет написать
программу, которая позволит присваивать оценки ученикам, указывая только
имя ученика. Для этого используйте контейнер map: имя ученика — ключ,
оценка (тип char) — значение.
Реализуйте перегрузку оператора [] для этого класса. Функция перегрузки
должна принимать параметр std::string (имя ученика) и возвращать ссылку
на его оценку. В функции перегрузки сначала выполните поиск указанного
имени ученика. Если ученик нашелся, то возвращайте ссылку на его
оценку.
English     Русский Rules