Примеры перегрузки операций
Перегрузка операции присваивания:
a) для случая, когда перевыделения памяти не происходит
class BadSize {}; //
class Vector {
const int size;
double *const data;
public:
Vector &operator=(const Vector &);
...
};
Vector & Vector::operator=(const Vector &v)
{ if(size!=v.size)
throw BadSize();
for(int i=0;i<size;++i)
data[i]=v.data[i];
return *this;
}
б) для случая, когда память перевыделяется
class String {
int len;
char * str;
public:
String &operator=(const String &);
...
};
String & String::operator=(const String &s)
{ String t(s); //
std::swap(len,t.len); //
std::swap(str,t.str);
return *this; //
}
Определение постфиксного ++ через префиксный:
class A {
...
public:
A& operator++();
};
inline A operator++(A &x, int)
{ A t(x);
++x;
return t;
}
Определение
+ через
+= :
class A {
...
public:
A& operator+=(const A&);
};
inline A operator+(A x, const A &y) //
{ return x+=y;
}
Определение
!= > >= <= через
== и
< в C++17:
#include <utility>
using namespace std::rel_ops;
class A {
...
public:
friend bool operator==(const A&, const A&);
friend bool operator<(const A&, const A&);
};
В явном виде эти операции нужно определять всегда так:
inline bool operator!=(const A &x, const A &y) //
{ return !(x==y);
}
inline bool operator>(const A &x, const A &y)
{ return y<x;
}
inline bool operator>=(const A &x, const A &y)
{ return !(x<y);
}
inline bool operator<=(const A &x, const A &y)
{ return !(y<x);
}
Использование нового оператора в C++20:
#include <compare>
class A {
...
friend auto operator<=>(const A&, const A&) = default;
};
По умолчанию сравнение полей выполняется в порядке перечисления в классе. В случае явного определения нужно вернуть значение типа
strong_ordering (одинаковые значения неразличимы),
weak_ordering (одинаковые значения различимы, например, сравнение без учета регистра) или
partial_ordering (сравнение возможно не всегда, например, с NaN для вещественных чисел), в которых определены константы less, great, equal (для
strong_ordering), equivalent (для
weak_ordering и
partial_ordering, unordered (для
partial_ordering).
Перегрузка операции индексирования:
class BadIndex {}; //
class Vector {
const int size;
double *const data;
public:
double &operator[](int); //
double operator[](int) const; //
...
};
double & Vector::operator[](int i)
{ if(i<0 || i>=size)
throw BadIndex();
return data[i];
}
double Vector::operator[](int i) const
{ if(i<0 || i>=size)
throw BadIndex();
return data[i];
}
int main()
{ Vector a(10); //
a[4]=a[5]*2; //
}
В C++23 можно перегружать операцию
[] для индексации по двум или более ключам:
class Matrix {
public:
Matrix(int n, int m);
double &operator[](int i, int j);
double operator[](int i, int j) const;
};
int main()
{ Matrix a(10,10); //
a[4,5]=1; //
}
Перегрузка
&,
-> и
*:
class A;
class Ptr { //
public:
A *operator->();
A &operator*();
...
};
class A {
public:
Ptr operator&(); //
...
};
Перегрузка операции
() для создания функционалов:
struct str_less { //
bool operator()(const char *a, const char *b)
{ return strcmp(a,b)<0;
}
};
int main()
{ char *s[100];
sort(s,s+100,str_less()); //
}
Перегрузка операций
<< и
>> ввода-вывода:
class Point {
double x,y;
public:
friend istream &operator>>(istream &, Point&);
friend ostream &operator<<(ostream &, const Point&);
};
istream &operator>>(istream &s, Point &p)
{ char c;
return s>>c>>p.x>>c>>p.y>>c; //
}
ostream &operator<<(ostream &s, const Point &p);
{ return s<<"("<<p.x<<","<<p.y<<")"; //
}
Формат ввода должен точно соответствовать формату вывода, не должно быть подсказок на ввод.
Чтобы проверить формат ввода
istream &operator>>(istream &s, Point &p)
{ char c;
if(!(s>>ws && //
s.peek()=='(' && s>>c>>p.x>>ws && s.peek()==',' &&
s>>c>>p.y>>ws && s.peek()==')' && s>>c))
s.clear(ios_base::failbit);
return s;
}
//
while(!(cin>>p)) {
//
cin.clear(); //
cin.ignore(256,'\n'); //
//
}
//
cin.exceptions(ios_base::failbit);
cin>>p;