Lect13
.pdfПерегрузкапрефикснойформы инкрементаидекремента
Постфикснаяоперациявыполняетмодификацию объектаивозвращаетвременнуюконстантную копиюобъектадомодификации
◦Копиядолжнабытьконстантной,чтобынедопустить операцийвроде:
counter++ -= 3;
Синтаксиспостфикснойформыопераций:
◦Type const operator++(int)
◦Type const operator--(int)
◦Целочисленныйпараметрявляетсяфиктивнымислужит лишьдляразличияотпрефикснойформы
Сточкизренияздравогосмыслапостфиксную формуоперацийинкрементаидекрементаследует
основыватьнаихпрефикснойформе |
41 |
|
Пример:счетчик
class Counter { public:
explicit Counter(unsigned maxValue,counter=0) :m_maxValue(maxValue), m_counter(counter){}
unsigned GetValue()const{return m_counter;} unsigned GetMaxValue()const{return m_maxValue;}
Counter& operator++() { ++m_counter;
if (m_counter>=m_maxValue){ m_counter = 0;
}
return *this;
}
Конструкторможет бытьпомечен как явный при помощи ключевого словаexplicit ,чтобызапретить возможностьегонеявного вызова вситуациях,вродеследующих:
CCounter counter(20, 5); counter=10;
эквивалентно:
CCounter counter(20, 5);
counter=CCounter(10, 0);
42
Пример:счетчик
//постфиксная форма инкремента
Counter const operator++(int) {
//создаем копию, выполняем префиксный
//инкремент, возвращаем копию
Counter tmpCopy(*this); ++*this;
return tmpCopy;
}
private:
unsigned m_maxValue, m_counter; };
43
Перегрузкаоперацийпотокового ввода-вывода
Перегрузкаоперацийформатированного ввода-выводавпотокиSTL неможетбыть выполненавнутрисамихклассовпотоков:
◦ВнесениемодификацийвSTL запрещено Стандартом
◦Объектыпотоковникоимобразомнесвязаныс пользовательскимитипамиданных
Дляперегрузкиоператоровввода-вывода следуетобъявлять ихвнекласса
Операторыформатированноговводавыводадолжнывозвращать ссылкунапоток
44
Выводпотокдлякласса"счетчик"
//выводим информацию о счетчике в виде
//[val/maxVal] в произвольный поток вывода template <class T>
std::basic_ostream<T>& operator<< (std::basic_ostream<T>& stream,
Counter const& counter) {
stream << "[" << counter.GetValue() << "/« << counter.GetMaxValue() << "]";
return stream;
}
45
Перегрузкачтенияизпотокадля
класса"счетчик"
template <class T> std::basic_istream<T>& operator>>
( std::basic_istream<T>& stream, Counter & counter){ std::streamoff pos = stream.tellg();
unsigned maxValue = 0; unsigned currentValue = 0; if ((stream.get() == '[')
&&(stream >> currentValue)
&&(stream.get() == '/')
&&(stream >> maxValue)
&&(stream.get() == ']')) {
counter = Counter(maxValue, currentValue); return stream;
}
46
Перегрузкачтенияизпотокадля класса"счетчик"
stream.seekg(pos);
stream.setstate(
std::ios_base::failbit | stream.rdstate()); return stream;
}
//Пример использования
int main(int argc, char* argv[]){ Counter c(10);
//Читаем в формате [counter/maxValue] cin >> c;
//Выводим в формате [counter/maxValue] cout << c;
return 0;
} |
47 |
Умныеуказатели(Smart Pointers)
Умныйуказатель(smart pointer) – класс(обычношаблонный), имитирующийинтерфейсобычного указателяидобавляющийновую функциональность.Реализация:
◦Перегрузкаопераций* и->,специфичных дляпростыхуказателей
◦Инкапсуляция семантикивладения ресурсомдляборьбысутечкамипамятии «висячими» ссылками
48
Примерумногоуказателя
class MyClassPtr { public:
MyClassPtr(MyClass * pMyClass):m_pMyClass(pMyClass){}
//деструктор автоматически
//удаляет управляемый объект
~MyClassPtr(){delete m_pMyClass;}
MyClass* operator->() { assert(m_pMyClass != NULL); return m_pMyClass;
} |
49 |
Примерумногоуказателя
MyClass& operator*() { assert(m_pMyClass != NULL); return * m_pMyClass;
}
private:
//запрещаем копирование и
//присваивание указателей
MyClassPtr(MyClassPtr const&);
MyClassPtr& operator= (MyClassPtr const&);
MyClass *m_pMyClass; };
50