Operator overloading allows operators like +, -, *, etc. to be redefined to work on user-defined types like classes. This is done by defining member functions for the operators. For example, to overload + to add two Distance objects, a member function Distance operator+(Distance) would be defined. Overloading operators allows user-defined types to be used in expressions like built-in types for a more natural interface. Some common operators that can be overloaded include arithmetic, relational, logical, and assignment operators. There are some restrictions like not changing operator precedence or number of operands.