C++ Operator Overloading
Operators are language features.
They can be given a user defined meaning to
create intuitive APIs.
Syntactic sugar, do not misuse!
Syntax for overloaded operator op:
returntype operatorop(argumentlist)
01.12.2010 Sascha Zelzer mbi@dkfz
Available Operators
Overloadable operators:
+ - * / % ^ & ->
! = < > += -= *= ()
^= &= |= << >> >>= <<= []
| ~! /= %= == != <= new
>= && || ++ -- , ->* delete
Member function only:
= () [] ->
Non-overloadable:
sizeof typeid . .* :: ?:
Everyday usages
Everybody uses overloaded operators
int a, b = 2;
a = &b; // int* operator&(int)
a = b & b; // int operator&(int, int)
std::string text;
text = ”hello”; // std::string& std::string::operator=(const char*)
char& c = text[1]; // char& std::string::operator[](size_t)
itk::SomeFilter::Pointer filter = itk::SomeFilter::New();
filter>Update(); // T* itk::SmartPointer::operator>() const
Example I
Overloading the +-operator
class Vector {
public:
Vector operator+(const Vector& vec) const;
};
class Point {
public:
Point operator+(const Vector& vec) const;
};
Vector v, w;
Point x, y;
x + y; // illegal: +-operator not defined
y = x + (v + w); // okay
Example II
How can we write ”std::cout << myClass” ?
class MyClass {
public:
std::string toString() const;
};
std::ostream& operator<<(std::ostream& os, const MyClass& mc)
{
os << mc.toString();
return os;
}
MyClass myClass;
std::cout << myClass << 23;
Rules of Thumb
Use common sense. This is the most important!
Maintain usual arithmetic identities: x == x+y-y
Constructive operators should return by value.
Constructive operators should not change their
operands.
Subscript operators generally come in pairs
(const and non-const)
Avoid overloading the comma operator: x, y
Avoid overloading short-circuiting operators: x ||
y or x && y. They evaluate both operands.
Copy Assignment Operator
C++ creates a default assignment operator for
your class. This might not do what you want!
class MyClass : public SuperClass MyClass&
{ MyClass::operator=(const MyClass& o)
SomeClass* some; // owning semantics {
if (this != &o) {
public: SomeClass* tmp = 0;
MyClass() : some(new SomeClass()) { } try {
~MyClass() { delete some; } tmp = new SomeClass(*o.some);
}; } catch (…) {
delete tmp; throw;
MyClass* a = new MyClass(); }
MyClass b;
b = *a; // b is leaking memory SuperClass::operator=(o);
delete a; // now b.some points to delete some;
// deleted memory some = tmp;
}
return *this;
}