15.7. Операторы инкремента и декремента
15.7. Операторы инкремента и декремента
Продолжая развивать реализацию класса ScreenPtr, введенного в предыдущем разделе, рассмотрим еще два оператора, которые поддерживаются для встроенных указателей и которые желательно иметь и для нашего интеллектуального указателя: инкремент (++) и декремент (--). Чтобы использовать класс ScreenPtr для ссылки на элементы массива объектов Screen, туда придется добавить несколько дополнительных членов.
Сначала мы определим новый член size, который содержит либо нуль (это говорит о том, что объект ScreenPtr указывает на единственный объект), либо размер массива, адресуемого объектом ScreenPtr. Нам также понадобится член offset, запоминающий смещение от начала данного массива:
class ScreenPtr {
public:
// ...
private:
int size; // размер массива: 0, если единственный объект
int offset; // смещение ptr от начала массива
Screen *ptr;
};
Модифицируем конструктор класса ScreenPtr с учетом его новой функциональности и дополнительных членов,. Пользователь нашего класса должен передать конструктору дополнительный аргумент, если создаваемый объект указывает на массив:
class ScreenPtr {
public:
ScreenPtr( Screen &s , int arraySize = 0 )
: ptr( &s ), size ( arraySize ), offset( 0 ) { }
private:
int size;
int offset;
Screen *ptr;
};
С помощью этого аргумента задается размер массива. Чтобы сохранить прежнюю функциональность, предусмотрим для него значение по умолчанию, равное нулю. Таким образом, если второй аргумент конструктора опущен, то член size окажется равен 0 и, следовательно, такой объект будет указывать на единственный объект Screen. Объекты нового класса ScreenPtr можно определять следующим образом:
Screen myScreen( 4, 4 );
ScreenPtr pobj( myScreen ); // правильно: указывает на один объект
const int arrSize = 10;
Screen *parray = new Screen[ arrSize ];
ScreenPtr parr( *parray, arrSize ); // правильно: указывает на массив
Теперь мы готовы определить в ScreenPtr перегруженные операторы инкремента и декремента. Однако они бывают двух видов: префиксные и постфиксные. К счастью, можно определить оба варианта. Для префиксного оператора объявление не содержит ничего неожиданного:
class ScreenPtr {
public:
Screen& operator++();
Screen& operator--();
// ...
};
Такие операторы определяются как унарные операторные функции. Использовать префиксный оператор инкремента можно, к примеру, следующим образом: const int arrSize = 10; Screen *parray = new Screen[ arrSize ]; ScreenPtr parr( *parray, arrSize ); for ( int ix = 0; ix
Определения этих перегруженных операторов приведены ниже:
Screen& ScreenPtr::operator++()
{
if ( size == 0 ) {
cerr "не могу инкрементировать указатель для одного объекта ";
return *ptr;
}
if ( offset = size - 1 ) {
cerr "уже в конце массива ";
return *ptr;
}
++offset;
return *++ptr;
}
Screen& ScreenPtr::operator--()
{
if ( size == 0 ) {
cerr "не могу декрементировать указатель для одного объекта ";
return *ptr;
}
if ( offset = 0 ) {
cerr "уже в начале массива ";
return *ptr;
}
--offset;
return *--ptr;
}
Чтобы отличить префиксные операторы от постфиксных, в объявлениях последних имеется дополнительный параметр типа int. В следующем фрагменте объявлены префиксные и постфиксные варианты операторов инкремента и декремента для класса ScreenPtr:
class ScreenPtr {
public:
Screen& operator++(); // префиксные операторы
Screen& operator--();
Screen& operator++(int); // постфиксные операторы
Screen& operator--(int);
// ...
};
Ниже приведена возможная реализация постфиксных операторов:
Screen& ScreenPtr::operator++(int)
{
if ( size == 0 ) {
cerr "не могу инкрементировать указатель для одного объекта ";
return *ptr;
}
if ( offset == size ) {
cerr "уже на один элемент дальше конца массива ";
return *ptr;
}
++offset;
return *ptr++;
}
Screen& ScreenPtr::operator--(int)
{
if ( size == 0 ) {
cerr "не могу декрементировать указатель для одного объекта ";
return *ptr;
}
if ( offset == -1 ) {
cerr "уже на один элемент раньше начала массива ";
return *ptr;
}
--offset;
return *ptr--;
}
Обратите внимание, что давать название второму параметру нет необходимости, поскольку внутри определения оператора он не употребляется. Компилятор сам подставляет для него значение по умолчанию, которое можно игнорировать. Вот пример использования постфиксного оператора:
const int arrSize = 10;
Screen *parray = new Screen[ arrSize ];
ScreenPtr parr( *parray, arrSize );
for ( int ix = 0; ix
При его явном вызове необходимо все же передать значение второго целого аргумента. В случае нашего класса ScreenPtr это значение игнорируется, поэтому может быть любым:
parr.operator++(1024); // вызов постфиксного operator++
Перегруженные операторы инкремента и декремента разрешается объявлять как дружественные функции. Изменим соответствующим образом определение класса ScreenPtr:
class ScreenPtr {
// объявления не членов
friend Screen& operator++( Screen & ); // префиксные операторы
friend Screen& operator--( Screen & );
friend Screen& operator++( Screen &, int); // постфиксные операторы
friend Screen& operator--( Screen &, int);
public:
// определения членов
};
Упражнение 15.7
Напишите определения перегруженных операторов инкремента и декремента для класса ScreenPtr, предположив, что они объявлены как друзья класса.
Упражнение 15.8
С помощью ScreenPtr можно представить указатель на массив объектов класса Screen. Модифицируйте перегруженные operator*() и operator () (см. раздел 15.6) так, чтобы указатель ни при каком условии не адресовал элемент перед началом или за концом массива. Совет: в этих операторах следует воспользоваться новыми членами size и offset.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
Операторы
Операторы В JScript поддерживаются операторы различных типов, которые похожи на операторы языка
Операторы отношения и логические операторы
Операторы отношения и логические операторы Операторы отношения используются для сравнения значений двух переменных. Эти операторы, описанные в табл. П2.11, могут возвращать только логические значения true или false.Таблица П2.11. Операторы отношения Оператор Условие, при
Операторы
Операторы Операторов язык JavaScript поддерживает очень много — на все случаи жизни. Их можно разделить на несколько
Операторы
Операторы Операторов язык JavaScript поддерживает очень много — на все случаи жизни. Их можно разделить на несколько групп. Арифметические операторы Арифметические операторы служат для выполнения арифметических действий над числами. Все арифметические операторы,
5.3.3 Операторы && и ||
5.3.3 Операторы && и || Операторы и || являются управляющими операторами. Если в командной строке стоит command1 command2, то command2 выполняется в том, и только в том случае, если статус выхода из команды command1 равен нулю, что говорит об успешном ее завершении. Аналогично, если
5.5.1 Операторы ›, ‹ и ››
5.5.1 Операторы ›, ‹ и ›› Для обозначения перенаправления используются символы "›", "‹" и "››". Чаще всего используется перенаправление вывода команды в файл. Вот соответствующий пример:[user]$ ls -l › /home/jim/dir.txtПо этой команде в файле /home/jim/dir.txt будет сохранен перечень файлов и
R.6 Операторы
R.6 Операторы Все операторы, за исключением оговоренных случаев, выполняются один за
4.5. Операции инкремента и декремента
4.5. Операции инкремента и декремента Операции инкремента (++) и декремента (--) дают возможность компактной и удобной записи для изменения значения переменной на единицу. Чаще всего они используются при работе с массивами и коллекциями – для изменения величины индекса,
Операторы SQL
Операторы SQL Оператор SQL используется для выполнения запроса к базе данных. Язык запросов выражается в операторах, которые задают цель: что должно быть сделано (операция), объекты, с которыми это должно быть сделано, и детализация, как это должно быть сделано. По теории
Операторы SQL
Операторы SQL Синтаксис SQL Firebird включает операторы для сравнения и вычисления значений столбцов, констант, переменных и выражений встраиваемого SQL для получения различных утверждений. Приоритет операторов Приоритет определяет порядок, в котором операторы и создаваемые
8.1. Операторы
8.1. Операторы присваиваниеvariable assignmentИнициализация переменной или изменение ее значения=Универсальный оператор присваивания, пригоден как для сравнения целых чисел, так и для сравнения строк.var=27category=minerals # Пробелы до и после оператора "=" -- недопустимы. Пусть вас не
Операторы
Операторы Операторы: обзор В PascalABC.NET определены следующие операторы.Операторы присваиванияСоставной операторОператор описания переменнойОператор цикла forОператор цикла foreachОператоры цикла while и repeatУсловный оператор ifОператор выбора варианта caseОператор вызова