Упражнение 7.25. Может ли класс Screen
безопасно полагаться на заданные по умолчанию версии операторов копирования и присвоения? Если да, то почему? Если нет, то почему?
Упражнение 7.26. Определите функцию Sales data::avg_price
как встраиваемую.
*this
Теперь добавим функции, устанавливающие символ в курсоре или в заданной области:
class Screen {
public:
Screen &set(char);
Screen &set(pos, pos, char);
//
};
inline Screen &Screen::set(char c) {
contents[cursor] = с; //
//
return *this; //
}
inline Screen &Screen::set(pos r, pos col, char ch) {
contents[r * width + col] = ch; //
//
return *this; //
}
Как и функция move()
, функция-член set()
возвращает ссылку на объект, из которого они вызваны (см. раздел 7.1.2). Возвращающие ссылку функции являются l-значениями (см. раздел 6.3.2), а это означает, что они возвращают сам объект, а не его копию. Это позволяет связать несколько их вызовов в одно выражение:
//
//
myScreen.move(4,0).set('#');
Эти операции выполнятся для того же объекта. В этом выражении сначала перемещается курсор (move()
) в окно (myScreen
), а затем устанавливается (set()
) заданный символ. Таким образом, этот оператор эквивалентен следующему:
myScreen.move(4,0);
myScreen.set('#');
Если бы функции move()
и set()
возвращали тип Screen
, а не Screen&
, этот оператор выполнялся бы совсем по-другому. В данном случае он был бы эквивалентен следующему:
//
Screen temp = myScreen.move(4,0); //
//
temp.set('#'); //
Если бы функция move()
имела возвращаемое значение не ссылочного типа, то оно было бы копией *this
(см. раздел 6.3.2). Вызов функции set()
изменил бы лишь временную копию, а не сам объект myScreen
.
*this
из константной функции-членаТеперь добавим функцию display()
, выводящую содержимое окна. Необходима возможность включать эту операцию в последовательность операций set()
и move()
. Поэтому, подобно функциям set()
и move()
, функция display()
возвратит ссылку на объект, для которого она выполняется.
Логически отображение объекта класса Screen
(окна) не изменяет его, поэтому функцию display()
следует сделать константным членом. Но если функция display()
будет константной, то this
будет указателем на константу, а значение *this
— константным объектом. Следовательно, типом возвращаемого значения функции display()
будет const Screen&
. Однако, если функция display()
возвратит ссылку на константу, мы не сможем вставить вызов функции display()
в последовательность действий:
Screen myScreen;
//
//
myScreen.display(cout).set('*');
Хотя объект myScreen неконстантный, вызов функции set()
не будет компилироваться. Проблема в том, что константная версия функции display()
возвращает ссылку на константу, и мы не можем вызвать функцию set()
для константного объекта.
*this
как ссылку, должен быть ссылкой на константу.
Функции-члены вполне можно перегружать исходя из того, являются ли они константными или нет, причем по тем же причинам, по которым функцию можно перегружать исходя из того, является ли ее параметр указателем на константу (см. раздел 6.4). Неконстантная версия неприменима для константных объектов; она применима только для константных объектов. Для неконстантного объекта можно вызвать любую версию, но неконстантная версия будет лучшим соответствием.