ЯП_Си++_02_Перегрузка
.pdf§2. Перегрузка операций
Java люблю больше, чем C++, но в ней НЕТ перегрузки операций /
Как разрешить операциям языка C++ работать с объектами? Перегрузить эти операции!
1.«a = b» яснее и удобнее, чем «copy(a,b)».
2.Чтобы перегрузить операцию, надо написать функцию-операцию:
- метод специального вида |
Зачем? Из соображений эффективности |
|
(чтоб не тратить силы на get- и set-методы)! |
- глобальная функция (дружественная), в которой хотя бы один аргумент – это объект (указатель или ссылка на объект) класса, для которого перегружаем операцию.
|
2.1. Перегрузка одноместных (унарных) операций |
||
Еще раз напоминаю: с & не вызы- |
|
||
вается конструктор копирования. |
Метод |
||
// |
time.h |
||
- параметров нет |
|||
Time& operator ++(); |
- операндом является объект, вызвавший метод |
||
//--------------- |
time.cpp--------------- |
Time& Time::operator ++(){ if(second<59) ++second; else { second = 0;
if (minute < 59) ++minute; else { minute = 0;
if(hour < 23) ++hour; else hour = 0;
|
} |
|
|
|
} |
|
|
} |
return *this; |
||
main.cpp |
|||
// |
|||
|
Time t; |
||
|
(++t).printTime(); |
++t ≈ t.operator ++() |
Дружественная функция
// |
---------------time.h--------------- |
|
|
|
friend Time& operator ++ (Time&); |
|
|
||
//--------------- |
main.cpp--------------- |
- один параметр – объект |
||
Time& operator ++(Time& t){ |
||||
|
if (t.second<59) ++t.second; |
(или ссылка на объект) класса. |
||
|
else { t.second = 0; |
- операнд – объект-параметр |
||
|
if (t.minute < 59) ++t.minute; |
|
|
|
|
else { t.minute = 0; |
|
|
|
|
if (t.hour < 23) ++t.hour; else t.hour = 0; |
|||
|
} |
|
|
|
|
} |
|
|
|
} |
return t; |
|
|
|
main.cpp |
|
|
||
//--------------- |
|
|
||
|
Time t; |
|
|
|
|
(++t) .printTime(); |
++t ≈ t.operator ++(t) |
|
Рассмотрели префиксный инкремент. Он предпочтительнее.
Постфиксные инкремент и декремент
Нет & - потери производительности
//--------------- |
time.h--------------- |
|
|
|
Time operator ++ (int); |
|
Первый параметр int. |
||
//--------------- |
time.cpp--------------- |
Используется только для того, чтобы |
||
Time Time::operator ++ (int){ |
||||
отличить от префиксной формы. |
||||
Time t_old = *this; |
|
|||
if(second<59) ++second; |
|
|||
else { second = 0; |
++minute; |
|
||
if (minute < 59) |
|
|||
else { |
minute = 0; |
|
||
if(hour < 23) ++hour; else hour = 0; |
||||
} |
|
|
|
|
} |
|
|
|
|
return t_old; |
|
|
||
} |
main.cpp |
|
||
//--------------- |
|
|||
Time t; |
|
|
|
(t++).printTime(); t++ ≈ t.operator ++(0)
|
2.2. Перегрузка двуместных (бинарных) операций |
|
Метод |
// |
---------------time.h--------------- |
bool operator > (Time&); |
|
//--------------- |
time.cpp--------------- |
bool Time::operator > (Time& t){ |
int i1 |
= hour*3600 + |
minute*60 + second; |
|
int i2 |
= |
t.hour*3600 |
+ t.minute*60 + t.second; |
if (i1 |
> |
i2) |
|
|
return true; |
- один параметр – второй (правый) операнд |
|||
else |
- первым (левым) операндом является |
||||
} |
return false; |
объект, вызвавший метод |
|||
main.cpp |
|||||
//--------------- |
|||||
Time t (10), t1 (20); |
|
|
|
||
if (t > t1) t.printTime(); |
t > t1 ≈ t.operator >(t1) |
|
|||
else |
t1.printTime(); |
|
|
|
Дружественная функция |
//--------------- |
time.h--------------- |
friend bool operator > (Time&, Time&); t > t1 ≈ operator >(t,t1)
-два параметра – объекты (или ссылки на объекты) класса.
-операнды – объекты-параметры
Хороший стиль программирования:
если не меняются значения полей объекта, то
-лучше делать метод константным
-лучше делать ссылки на объекты-параметры константными
bool operator > (const Time&) const; bool Time::operator > (Time& t) const {
или
friend bool operator > (const Time&, const Time&);
Оба объекта существуют!
2.3.Перегрузка операции присваивания
1.Операция «=» по умолчанию – поэлементное копирование.
2.Когда необходимо перегрузить? См. конструктор копирования!
3.Возвращаемое значение и параметр.
Ссылка на объект, для которого |
Ссылка на присваиваемый объ- |
эта операция вызвана (левый). |
ект (правый). |
|
|
|
|
|
|
|
|
Только метод |
|
Не наследуется |
|
|
|
|||||||
// |
--------------- |
|
|
|
|
time.h--------------- |
||||||||||||||
Time& operator = (const Time&); |
||||||||||||||||||||
// |
|
|
|
|
|
|
|
|
|
|
|
|
|
Можно ли убрать эту проверку? |
||||||
|
|
|
|
|
time.cpp--------------- |
|||||||||||||||
Time& Time::operator =(const Time& t){ |
||||||||||||||||||||
|
|
|
//проверка на самоприсваивание |
|
|
|
|
|
||||||||||||
|
|
|
if (&t == this) return *this;//сравнение адресов |
|
||||||||||||||||
|
|
if (stime) delete[] stime; |
|
|
|
|
||||||||||||||
|
|
|
if (t.stime){ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
stime = new char [strlen(t.stime)+1]; |
|
||||||||||||||||
|
|
|
strcpy(stime,t.stime); |
|
|
|
||||||||||||||
|
|
} else |
|
|
|
|
|
|
|
|||||||||||
|
|
|
|
|
|
|
||||||||||||||
|
|
|
stime = 0; |
|
|
|
|
|
||||||||||||
|
|
hour = t.hour; |
|
|
|
|
|
|||||||||||||
|
|
minute = t.minute; |
|
|
||||||||||||||||
|
|
second = t.second; |
|
|
||||||||||||||||
|
|
|
|
|
|
|||||||||||||||
} |
|
return *this; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
Эта часть есть в конструкторах |
|
Этой части нет в конструкторах
//---------------main.cpp---------------
Time t (10,10,10,"1"), t1, t2; t1.printTime(); t2.printTime();
t2 = t1 = t; //ассоциативность операции «=»? t1.printTime();
t2.printTime();
t1 = t ≈ t1.operator =(t)
2.4. Перегрузка операции приведения типа
Только метод
-нет параметров
-тип возвращаемого значения не указывается
// |
time.h |
Можно не только |
стандартный, но и |
||
operator int(); |
time.cpp |
пользовательский тип |
//--------------- |
|
|
Time::operator int (){ |
|
|
return hour*3600 + minute*60 + second; |
|
|
} |
main.cpp |
|
//--------------- |
|
Time t (10,10,10,"1");
printf("%i\n", int(t)); int(t) ≈ t.operator int()
Так же, как и конструктор преобразования, операция приведения типа может вызываться автоматически!
Time t (10,10,10,"1"); printf("%i\n",t);