Каноническая форма оператора + = для классов

Я знаю, что это хорошая идея сделать как можно больше интерфейса класса, не являющегося членом, не другом, и я только что понял, что для моего класса 3D-векторов, 'Vector3', я могу переместить + =, - = и другие операторы вне класса, оставляя только конструкторы и оператор присваивания копии.

Возникает вопрос: как должен выглядеть этот оператор? Я видел канонические формы множества других операторов и следовал их советам, но я не видел канонических форм этих операторов. Я привел то, что, по моему мнению, должно быть ниже.

Второй вопрос: как вообще называются эти операторы? Операторы арифметического присваивания?

(Соответствующий) код перед:

class Vector3 {
public:
    Vector3& operator+=(const Vector3& rhs);
    float x, y, z;
};

Vector3& Vector3::operator+=(const Vector3 &rhs) {
    x += rhs.x;
    y += rhs.y;
    z += rhs.z;

    return *this;
}

Что я изменил до сих пор:

class Vector3 {
public:
    float x, y, z;
};

Vector3& operator+=(Vector3& lhs, const Vector3& rhs) {
    lhs.x += rhs.x;
    lhs.y += rhs.y;
    lhs.z += rhs.z;

    return lhs;
}

person Ben Hymers    schedule 16.05.2009    source источник
comment
Поскольку вы спросили их имя: они называются операторами составного присваивания   -  person Johannes Schaub - litb    schedule 17.05.2009


Ответы (3)


Мне нравится то, что у вас есть.

Кстати, когда вы переходите к оператору +, это обычно реализуется в терминах + =. (создайте копию lhs, затем вызовите lhs + = rhs и верните результат)

Не знаю, знаете ли вы об этом приеме, но, поскольку вас беспокоят канонические способы реализации этих операторов, не помешает упомянуть об этом. :)

person jalf    schedule 16.05.2009
comment
Честно говоря, я приму ваш ответ, так как вы пришли на две минуты раньше других ребят;) Я знаю об этом, но другие, читающие это, могут не знать, так что спасибо за упоминание! - person Ben Hymers; 17.05.2009

То, что у вас есть, выглядит хорошо.

Основной способ подумать об этом интуитивно - подумать о том, как вы хотите, чтобы код выглядел, когда вы его пишете. Если в этом случае вы можете написать

Vector v, w;

v += w;
w += v;

и так далее, вы на правильном пути.

Есть много хороших практических правил, которые могут помочь; см. эту запись в часто задаваемых вопросах по C ++.

person Charlie Martin    schedule 16.05.2009

Я бы не сказал «как можно больше интерфейса». Мало что можно получить, сделав operator+=, operator-= и т. Д. Не-другом-не-участником.

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

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

Есть конкретные причины, чтобы сделать определенные функции и операторы "не-дружественными, не-членами". Например, оператор ‹< () при использовании в качестве «оператора вставки потока» не может быть членом, потому что вам придется изменить класс lhs (поток).

person Euro Micelli    schedule 16.05.2009
comment
В этом случае на самом деле уже есть много функций, не являющихся членами, поскольку иногда полезно выполнять преобразования типов левого объекта, поэтому, если что-то, выглядит более аккуратной кластеризацией всех функций вне класса, а не разделением их между член и не член :) В целом хороший совет, спасибо. - person Ben Hymers; 17.05.2009
comment
Я не согласен. Если функции или оператору не нужен доступ к закрытым переменным, зачем давать им доступ? Да, мы можем просто отказаться от доступа к ним при написании функции, но что позже, когда мы будем отлаживать код? Или тестируем класс? Мы должны по крайней мере изучить все функции-члены, чтобы увидеть, не делают ли они что-нибудь неприятное для закрытых членов. Итак, если у вас есть возможность, почему бы не оставить оператор + = вне класса? Где стоимость? - person jalf; 17.05.2009
comment
@jalf: да, я с тобой. Полностью; правда, обещаю. Я не решился опубликовать это. Но - позвольте мне шокировать моих друзей и коллег - иногда я действительно могу быть прагматичным: такие операторы обычно трехстрочные, классы, которые их используют, обычно являются типами значений, их обычно полдюжины. , и они, как правило, довольно тривиальны. Тогда на практике это просто не имеет значения. Я лучше сосредоточусь на методах "страница плюс длинная". - person Euro Micelli; 18.05.2009