<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://mit.spbau.ru/sewiki/index.php?action=history&amp;feed=atom&amp;title=%D0%9F%D0%B5%D1%80%D0%B5%D0%B3%D1%80%D1%83%D0%B7%D0%BA%D0%B0_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D0%BE%D0%B2</id>
		<title>Перегрузка операторов - История изменений</title>
		<link rel="self" type="application/atom+xml" href="http://mit.spbau.ru/sewiki/index.php?action=history&amp;feed=atom&amp;title=%D0%9F%D0%B5%D1%80%D0%B5%D0%B3%D1%80%D1%83%D0%B7%D0%BA%D0%B0_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D0%BE%D0%B2"/>
		<link rel="alternate" type="text/html" href="http://mit.spbau.ru/sewiki/index.php?title=%D0%9F%D0%B5%D1%80%D0%B5%D0%B3%D1%80%D1%83%D0%B7%D0%BA%D0%B0_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D0%BE%D0%B2&amp;action=history"/>
		<updated>2026-06-03T20:13:41Z</updated>
		<subtitle>История изменений этой страницы в вики</subtitle>
		<generator>MediaWiki 1.26.2</generator>

	<entry>
		<id>http://mit.spbau.ru/sewiki/index.php?title=%D0%9F%D0%B5%D1%80%D0%B5%D0%B3%D1%80%D1%83%D0%B7%D0%BA%D0%B0_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D0%BE%D0%B2&amp;diff=132&amp;oldid=prev</id>
		<title>Mariyafomkina: Новая страница: «== Общая информация == Перегрузка операторов бывает полезна, например, в следующих случаях: …»</title>
		<link rel="alternate" type="text/html" href="http://mit.spbau.ru/sewiki/index.php?title=%D0%9F%D0%B5%D1%80%D0%B5%D0%B3%D1%80%D1%83%D0%B7%D0%BA%D0%B0_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D0%BE%D0%B2&amp;diff=132&amp;oldid=prev"/>
				<updated>2011-03-20T11:45:57Z</updated>
		
		<summary type="html">&lt;p&gt;Новая страница: «== Общая информация == Перегрузка операторов бывает полезна, например, в следующих случаях: …»&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая страница&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== Общая информация ==&lt;br /&gt;
Перегрузка операторов бывает полезна, например, в следующих случаях:&lt;br /&gt;
# Вместо get(i) удобнее использовать [i].&lt;br /&gt;
# a.plus(b) или plus(a, b) удобнее заменить на a + b.&lt;br /&gt;
# Вместо p.get()-&amp;gt;print() удобнее использовать p-&amp;gt;print().&lt;br /&gt;
# Обобщённое программирование.&lt;br /&gt;
В С++ существуют следующие операторы:&lt;br /&gt;
* +a -a&lt;br /&gt;
* + - / * %&lt;br /&gt;
* += -= /= *= %=&lt;br /&gt;
* &amp;amp;&amp;amp; || !&lt;br /&gt;
* = == !=&lt;br /&gt;
* &amp;amp; | ~&lt;br /&gt;
* a-&amp;gt; *a &amp;amp;a&lt;br /&gt;
* &amp;gt;&amp;gt; &amp;lt;&amp;lt;&lt;br /&gt;
* ,&lt;br /&gt;
* &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;. ::&amp;lt;/font&amp;gt;&lt;br /&gt;
* &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;()?():()&amp;lt;/font&amp;gt;&lt;br /&gt;
* [] ()&lt;br /&gt;
* a++ ++a a-- --a&lt;br /&gt;
* &amp;gt; &amp;lt; &amp;gt;= &amp;lt;=&lt;br /&gt;
* new, delete&lt;br /&gt;
* приведение к типу&lt;br /&gt;
Два последних типа операторов будут разобраны в отдельной лекции.&lt;br /&gt;
&lt;br /&gt;
Из всего этого списка нельзя перегружать те операторы, которые выделены красным цветом.&lt;br /&gt;
&lt;br /&gt;
Для перегрузки операторов характерны следующие особенности:&lt;br /&gt;
&lt;br /&gt;
* Для того, чтобы можно было перегрузить оператор, необходимо, чтобы хотя бы один из аргументов был пользовательского типа.&lt;br /&gt;
* Большую часть операторов можно перегружать как внутри класса, так и снаружи, причём их не нужно определять одновременно и там, и там. Однако некоторые операторы могут быть определены только внутри класса, а именно =, a-&amp;gt;, [], ().&lt;br /&gt;
* Для операторов &amp;amp;&amp;amp; и || применяется логика &amp;quot;ленивых&amp;quot; вычислений. При перегрузке этих операторов она теряется.&lt;br /&gt;
* Оператор -&amp;gt; должен обязательно возвращать указатель.&lt;br /&gt;
* Операторов () может быть сколько угодно, с различными сигнатурами.&lt;br /&gt;
* Оператор , в качестве результата возвращает тип и значение самого правого выражения. Перегружается он очень редко. Пример использования:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
a = f(), g();&lt;br /&gt;
//сначала вычисляется f(), потом g(), и a=f() &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Пример перегрузки оператора бинарного сложения ==&lt;br /&gt;
&lt;br /&gt;
Оператор бинарного сложения можно перегрузить снаружи класса следующим образом:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
BigNum operator+ (BigNum const &amp;amp;a, BigNum const &amp;amp;b)&lt;br /&gt;
{&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
А так будет выглядеть определение внутри:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
BigNum BigNum::operator+ (BigNum const &amp;amp;b) const&lt;br /&gt;
{&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
//первым аргументом в данном случае является *this&lt;br /&gt;
//метод не меняет значение, поэтому const&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Пример перегрузки оператора += ==&lt;br /&gt;
&lt;br /&gt;
Определение оператора снаружи класса выглядит следующим образом:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
BigNum &amp;amp; operator+= (BigNum &amp;amp;a, BigNum const &amp;amp;b)&lt;br /&gt;
{&lt;br /&gt;
	...&lt;br /&gt;
	return a;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
А определение внутри класса такое:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
BigNum &amp;amp; BigNum::operator+= (BigNum const &amp;amp;b) const&lt;br /&gt;
{&lt;br /&gt;
	...&lt;br /&gt;
	return *this;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В частности, можно передавать операнды различных типов (например, для перегрузки BigNum+int).&lt;br /&gt;
&lt;br /&gt;
== Другие примеры ==&lt;br /&gt;
&lt;br /&gt;
Определение унарного минуса снаружи класса:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
BigNum operator- (BigNum const &amp;amp;a)&lt;br /&gt;
{&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Он же - внутри класса:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
BigNum BigNum::operator- () const&lt;br /&gt;
{&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Далее показана разница между определением методов ++a и a++:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
BigNum &amp;amp; operator++ (BigNum &amp;amp;a);&lt;br /&gt;
BigNum &amp;amp; operator++ (BigNum &amp;amp;a, size_t);&lt;br /&gt;
//во втором случае используется фиктивный параметр, &lt;br /&gt;
//который нужен только для разделения префиксного и постфиксного инкрементов&lt;br /&gt;
BigNum BigNum::operator[] (size_t i); &lt;br /&gt;
BigNum BigNum::operator() (...); &lt;br /&gt;
...&lt;br /&gt;
BigNum b;&lt;br /&gt;
b(17, 34);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Примеры грамотного использования перегрузки операторов ==&lt;br /&gt;
=== Array ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct Array&lt;br /&gt;
{&lt;br /&gt;
	int operator[] (size_t i) const&lt;br /&gt;
	{&lt;br /&gt;
		assert (i&amp;lt;size_);&lt;br /&gt;
		return data_[i];&lt;br /&gt;
	}&lt;br /&gt;
	int &amp;amp; operator[] (size_t i)&lt;br /&gt;
	{&lt;br /&gt;
		return data_[i];&lt;br /&gt;
	}&lt;br /&gt;
	void swap (Array &amp;amp;a)&lt;br /&gt;
	{&lt;br /&gt;
		std::swap(a.data_, data_);&lt;br /&gt;
		std::swap(a.size_, size_);&lt;br /&gt;
	}&lt;br /&gt;
	//swap меняет значения местами &lt;br /&gt;
	Array &amp;amp; operator= (Array const &amp;amp;a)&lt;br /&gt;
	{&lt;br /&gt;
		if (this != &amp;amp;a)&lt;br /&gt;
			Array(a).swap(*this);&lt;br /&gt;
		return *this;			&lt;br /&gt;
	}&lt;br /&gt;
};	&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Можно подключить или отключить assert, это зависит от параметров компиляции. При выходе за границы массива тогда возникнет ошибка.&lt;br /&gt;
&lt;br /&gt;
Для использования ostream и istream достаточно подключить&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;iosfwd&amp;gt;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
т.к. iostream весьма и весьма велик.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
Array a;&lt;br /&gt;
std::cout &amp;lt;&amp;lt; a;&lt;br /&gt;
std::ostream &amp;amp;operator&amp;lt;&amp;lt; (std::ostream &amp;amp; os, Array const &amp;amp;a); &lt;br /&gt;
//этот и следующий операторы могут быть переопределены только снаружи класса &lt;br /&gt;
std::istream &amp;amp;operator&amp;gt;&amp;gt; (std::ostream &amp;amp; is, Array &amp;amp;a); &lt;br /&gt;
//при чтении объект изменяется (std::cin &amp;gt;&amp;gt; a) &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''Замечание:''' swap(Array(a)) не сработает, потому что swap принимает константную ссылку, а временные объекты нельзя передавать по константной ссылке.&lt;br /&gt;
=== BigNum ===&lt;br /&gt;
&lt;br /&gt;
Оператор += лучше определять внутри класса, а оператор + — через += снаружи, как показано в примере:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct BigNum&lt;br /&gt;
{&lt;br /&gt;
	BigNum &amp;amp; operator+= (BigNum &amp;amp;b)&lt;br /&gt;
	{&lt;br /&gt;
		...&lt;br /&gt;
	}&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
BigNum operator+ (BigNum a, BigNum const &amp;amp;b)&lt;br /&gt;
{&lt;br /&gt;
	return a+=b;&lt;br /&gt;
}&lt;br /&gt;
//+, определённый снаружи, может быть вызван от аргументов,&lt;br /&gt;
//которые может быть приведены к типу&lt;br /&gt;
BigNum a(10); //должен быть BigNum(int)&lt;br /&gt;
a+20;         //работает и внутри, и снаружи&lt;br /&gt;
20+a;         //работает только снаружи&lt;br /&gt;
bool operator== (BigNum const &amp;amp;a, BigNum const &amp;amp;b)&lt;br /&gt;
{&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
bool operator!= (BigNum const &amp;amp;a, BigNum const &amp;amp;b)&lt;br /&gt;
{&lt;br /&gt;
	return !(a==b);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Вообще говоря, достаточно определить &amp;lt; и == и легко получить все остальные сравнения. Например, (a&amp;lt;=b) выражается как (!(b&amp;lt;a))&lt;br /&gt;
=== Умные указатели ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	smart_pstr p = new ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В данном примере рассматривается перегрузка операторов p-&amp;gt; и *p.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct smart_pstr&lt;br /&gt;
{&lt;br /&gt;
	string *p_;&lt;br /&gt;
	...&lt;br /&gt;
	string * operator-&amp;gt; () const&lt;br /&gt;
	{&lt;br /&gt;
		return p_;&lt;br /&gt;
	}&lt;br /&gt;
	string &amp;amp; operator* () const&lt;br /&gt;
	{&lt;br /&gt;
		return *p_;&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
//предположим, что мы переопределим оператор ниже:&lt;br /&gt;
operator== (smart_pstr, smart_pstr)&lt;br /&gt;
...&lt;br /&gt;
smart_pstr p;&lt;br /&gt;
string *q;&lt;br /&gt;
p == q; //произойдёт неявное преобразование типа,&lt;br /&gt;
//создастся smart_pstr(q), а потом он будет удалён&lt;br /&gt;
//для того, чтобы этого избежать, нужно конструктор сделать explicit&lt;br /&gt;
//(т.е. запретить неявное преобразование типов)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mariyafomkina</name></author>	</entry>

	</feed>