2015-05-16 2 views
2

Недавно я недавно обнаружил, что сложные операторы присваивания (такие как operator+= или operator-=) могут быть перегружены вне класса.Почему перегруженные составные операторы присваивания являются функциями, не являющимися членами?

Рассмотрим:

class X { }; // A third party class 

// The following function is legal: 
X& operator+=(X& lhs, const X& rhs) { 
    // ... 
} 

Очевидно, что функция не-член не может касаться частного интерфейса X, поэтому нет инкапсуляции беспокойства здесь. Но похоже, что это часть собственного интерфейса X, чего явно нет.

Мне кажется, это может привести к серьезному злоупотреблению кодом и запутанному поведению. Представьте, что кто-то подумал, что было бы неплохо использовать его для некоторых «умных хаков» со стандартными, такими как std::vector или std::map.

Это особенно характерно, поскольку другие операторы, такие как operator[] и operator->, не могут быть функциями, не являющимися членами, что я и думал об этом.

Так почему же это разрешено?

+3

Я не вижу никаких проблем. – Columbo

ответ

3

Рассмотрим, если библиотека A определяет объект (скажем, объект Matrix). Библиотека B расширяет библиотеку A с некоторым подобным объектом (скажем, векторы).

Библиотека B хочет определить операторы, которые связывают матрицы с векторами (например, умножают). Но если определение этих перегрузок операторов должно было быть сделано в исходном объекте, писатели застряли бы, и пользователи остались бы в странной ситуации, когда они могли бы выполнять векторную матрицу, но не матричный вектор.

Чтобы посмотреть конкретно на + = и - =, как вы упомянули, рассмотрим матрицу размером 1 на n, которая по существу является вектором. Теперь мы хотим иметь возможность выполнять матрицу + = вектор.

Позволяя им быть определенными извне, избегает этой проблемы.

Мне кажется, это может привести к некоторому серьезному злоупотреблению коды и странному поведению

Совершенно верно. Но не забывайте, что это язык, который имеет встроенный препроцессор. Если другие разработчики хотят запутать вас, у них уже есть гораздо более мощные инструменты.

4

Так почему же это разрешено?

Вы просите нас прочитать ум Строустропа. Невозможно.
Но общий принцип C++ заключается не в том, чтобы ограничить разработчиков (мы не предоставляем стерилизованный набор инструментов, безопасных для игры. Мы предоставляем полный набор бритвенных пил и вращающихся цепей).

Мне кажется, это может привести к серьезному злоупотреблению кодом и запутанному поведению. Представьте, что кто-то подумал, что было бы неплохо использовать его для некоторых «умных хаков» со стандартными файлами, такими как std :: vector или std :: map.

Да, может.
Когда вы злоупотребляете перегрузкой оператора, это может привести к опасным и смертельным вещам.Лучше не делать этого (особенно для других народов или стандартных классов).

Но это может обеспечить потенциально полезную ситуацию (когда вы будете осторожны). Это особенно полезно, когда вы создаете числовой класс типа, поскольку он помогает с автоматическими преобразованиями, которые делают код более естественным для чтения.

Смежные вопросы