Каждый оператор имеет некий смысл, когда он используется для встроенных типов. Бинарный оператор +, например, всегда означает сумму. Вполне логично и удобно применять в классе бинарный оператор + для аналогичной функции. Например, библиотечный тип string, в соответствии с соглашением, общепринятым для множества языков программирования, использует оператор + для конкатенации, т.е. добавления содержимого одной строки в другую.
Перегруженные операторы полезней всего тогда, когда смысл встроенного оператора логически соответствует функции текущего класса. Применение перегруженных операторов вместо именованных функций позволяет сделать программы более простыми, естественными и интуитивно понятными. Злоупотребление перегруженными операторами, а также придание не свойственного им смысла сделает класс неудобным в применении.
На практике вполне очевидные случаи противоестественной перегрузки операторов довольно редки. Например, ни один ответственный программист не переопределил бы оператор operator+ для вычитания. Зато очень часто предпринимаются попытки неким образом приспособить "обычный" оператор, который неприменим к данному классу. Операторы следует использовать только для тех функций, которые будут однозначно поняты пользователями. Оператор с неоднозначным смыслом, например равенство, может быть интерпретирован по-разному.
Если класс обладает арифметическим (см. раздел 4.2) или побитовым (см. раздел 4.8) оператором, то его, как правило, имеет смысл снабдить соответствующими составными операторами. Вполне логично было бы также определить и оператор +=. Само собой разумеется, оператор += должен быть определен так, чтобы он вел себя аналогично встроенным операторам, т.е. осуществлял составное присвоение: сначала сумма (+), а затем присвоение (=).
При проектировании перегруженных операторов необходимо принять решение, должен ли каждый из них быть членом класса или обычной функцией (не членом класса). В некоторых случаях выбора нет; оператор должен быть членом класса. В других случаях можно принять во внимание несколько эмпирических правил, которые помогут принять решение.
Приведенный ниже список критериев может оказаться полезен в ходе принятия решения о том, следует ли сделать оператор функцией-членом класса или обычной функцией.
• Операторы присвоения (=), индексирования ([]), вызова (()) и доступа к члену класса (->)
• Подобно оператору присвоения, составные операторы присвоения
• Другие операторы, которые изменяют состояние своего объекта или жестко связаны с данным классом (например, инкремент, декремент и обращение к значению), обычно должны быть членами класса.
• Симметричные операторы, такие как арифметические, операторы равенства, операторы сравнения и побитовые операторы, лучше определять как обычные функции, а не члены класса.
Разработчики ожидают возможности использовать симметричные операторы в выражениях со смешанными типами. Например, возможности сложить переменные типа int и double. Сложение симметрично, а потому можно использовать тип как левого, так и правого операнда.
Если необходимо обеспечить подобные выражения смешанного типа, задействующие объекты класса, то оператор должен быть определен как функция, не являющаяся членом класса.
При определении оператора как функции-члена левый операнд должен быть объектом того класса, членом которого является этот оператор. Например: