Страницы

Поиск по вопросам

четверг, 13 февраля 2020 г.

C++, глобальные перегруженные операторы и операторы-члены

#cpp #перегрузка_операторов #операторы


Я никак не могу найти развернутую информацию по тому, когда перегруженные операторы
следует делать членами типа, а когда - глобальными и независимыми функциями.

Буду очень благодарен, если кто-нибудь поможет мне разобраться в этом вопросе.
    


Ответы

Ответ 1



Во-первых, есть несколько групп ситуаций, когда у вас просто нет возможности выбирать между этими двумя вариантами: Некоторые операторы разрешается перегружать только методами класса: =, (), [], ->. Ситуации, когда первый (или единственный) операнд оператора не является class-типом. Тогда перегрузка возможна только самостоятельной функцией. Например, оператор сложения int + myclass или инкремента myenum++. Ситуации, когда изменять определение класса первого операнда у вас нет возможности. Тогда перегрузка возможна только самостоятельной функцией. Всем нам знакомый пример: операторы ввода-вывода << и >> для стандартных потоков. Во-вторых, для остальных ситуаций жестких правил нет. Но можно порекомендовать использовать самостоятельные функции для таких семантически-симметричных бинарных операторов как арифметические операторы, логические операторы, побитовые операторы, операторы относительного сравнения и операторы сравнения на равенство. Для унарных операторов зачастую уместнее реализация методом класса. Для операторов составного присваивания (+= и т.п.) тоже интуитивно уместнее реализация методом класса (они сродни копирующему оператору присваивания =). Операторы сдвига << и >> - в зависимости от степени симметричности той семантики, которой вы их наделяете. Обратите также внимание, что в стандартной библиотеке низкоуровневые фундаментальные операторы форматированного ввода-вывода реализованы методами классов, в то время как более высокоуровневые "составные" операторы - самостоятельными функциями. То есть можно предложить и такой вариант разделения подходов к перегрузке операторов.

Ответ 2



Все очень просто. Если оператор модифицирует обьект, то его стоит делать членом класса, а когда оператор выполняет действие с другим обьектом и возвращает другой обьект(или ничего не возвращает), то лучше написать его как независимая функция, дабы избежать разбухания кода. Например: class Some_class { //... public: Some_class& operator+=(const Some_class&); Some_class& operator/=(const Some_class&); //... }; inline Some_class operator +(const Some_class&, const Some_class&); inline Some_class operator *(const Some_class&, const Some_class&); //... Одним словом вы сами создаете абстракцию. Вы можете написать так, как представляете(одни смотрят на собак как на друга, который умеет то то, то то, доугие могут смотреть на них как на зверей, которых нужно размножать для корма зверей в зоопарке). Если абстракция выражает только то, что умеет делать обьект или что можно выражать этим классом, то это хороший код(стиль), понятный читательям и пользовательям. Не нужно туда пихать все то, что могут делать пользователи с экземпляром, не то можно туда пихнуть сотни и тысяча функции и сущности....

Комментариев нет:

Отправить комментарий