Операторы перегрузки как функция-член или функция не-члена (друга)?
в настоящее время я создаю класс утилиты, в котором будут перегружены операторы. Каковы плюсы и минусы того, чтобы сделать их членом или не членом (friend
) функции? Или вообще разница? Может быть, для этого есть лучшая практика?
6 ответов
каждый оператор имеет свои собственные соображения. Например, оператор
Что касается разрешения специализации через наследование, общим шаблоном является реализация оператор-нечлен в терминах виртуальной функции-члена (например, оператор
Я бы пошел с "стандартами кодирования C++: 101 правила, рекомендации и рекомендации": Если вы можете сделать это как функция, не являющаяся членом, сделайте это как функция, не являющаяся членом (в том же пространстве имен).
одна из причин: он лучше работает с неявным преобразованием типов. Пример: у вас есть сложный класс с перегруженным оператором*. Если вы хотите написать 2.0 * aComplexNumber, вам нужно, чтобы оператор* был функцией, не являющейся членом.
другая причина: меньше соединения. Не-члены-функции менее тесно связаны, чем функции-члены. Это почти всегда хорошо.
если вы планируете реализовать операторы потоковой передачи (>), то они будут методами, не являющимися членами, потому что ваш объект находится слева от оператора.
если вы планируете реализовать ->, () или [] они, естественно, методы-члены.
для других (сравнение и математические) вы должны проверить импульс.Операторы, это действительно помогает.
например, если вы хотите реализовать следующие операторы:
MyClass& MyClass::operator+=(int);
MyClass operator+(const MyClass&, int);
MyClass operator+(int, const MyClass&);
вы только надо написать:
class MyClass: boost::operator::addable<MyClass,int> // no need for public there
{
public:
MyClass& operator+=(int);
private:
};
в 2 operator+
будет автоматически сгенерирован как нечлены, которые позволят вам воспользоваться автоматическими преобразованиями. И они будут эффективно реализованы в срок operator+=
таким образом, вы пишете код только один раз.
Если вы реализуете op, то, скорее всего, вам нужно реализовать op=. т. е. если вы перегружаете оператор+, то вы должны реализовать +=. Убедитесь, что вы возвращаете const объекту, если вы выполняете post-increment или перегрузку + operator. Итак , если вы перегрузите operator+, то реализуйте его как оператор, не являющийся членом, и используйте оператор += внутри него. Для EG.
const A operator+(const A& lhs, const A& rhs)
{
A ret(lhs);
ret += rhs;
return ret;
}
для двоичных операторов одним из ограничений функций-членов является то, что левый объект должен быть вашего типа класса. Это может ограничить использование оператора симметрично.
рассмотрим простой класс string:
class str
{
public:
str(const char *);
str(const str &other);
};
Если вы реализуете operator+ как функцию-член, в то время как str("1") + "2"
будет компилироваться, "1" + str("2")
не будет компилироваться.
но если вы реализуете operator+ как функцию, не являющуюся членом, то оба этих оператора будут законными.
нет ничего похожего на лучшие практики, но это зависит от оператора, который вы перегружаете ..
для e.г.
>> и не может быть перегружен как функции-члены .
Предположим, вы хотите сделать так:obj1 = 2 * obj2 перейти к функция, не являющаяся членом.
на бинарные перегрузку операторов функции-члена принимает только 1 параметр (вызов объекта impcliitly передается), в то время как функция, не являющаяся членом, принимает 2 параметра .