Оператор, перегружающийся вне класса [дубликат]

Этот вопрос уже имеет ответ здесь:

Существует два способа перегрузить операторы для класса C++:

В классе

class Vector2
{
public:
    float x, y ;

    Vector2 operator+( const Vector2 & other )
    {
        Vector2 ans ;
        ans.x = x + other.x ;
        ans.y = y + other.y ;
        return ans ;
    }
} ;

Вне класса

class Vector2
{
public:
    float x, y ;
} ;

Vector2 operator+( const Vector2& v1, const Vector2& v2 )
{
    Vector2 ans ;
    ans.x = v1.x + v2.x ;
    ans.y = v1.y + v2.y ;
    return ans ;
}

(По-видимому, в C# можно только использовать "вне класса" метод.)

В C++, какой путь более корректен? Который предпочтителен?

44
задан bobobobo 13 March 2010 в 02:37
поделиться

3 ответа

Основной вопрос: «Вы хотите, чтобы преобразования выполнялись в параметре левой части оператора?» . Если да, воспользуйтесь бесплатной функцией. Если нет, используйте члена класса.

Например, для operator + () для строк мы хотим, чтобы преобразования выполнялись, чтобы мы могли сказать такие вещи, как:

string a = "bar";
string b = "foo" + a;

где выполняется преобразование, чтобы превратить char * "foo " в std :: string . Итак, мы превращаем operator + () для строк в бесплатную функцию.

54
ответ дан 26 November 2019 в 22:08
поделиться

В Эффективном C ++ Мейера есть прекрасное обсуждение этой проблемы: Правило 24: «Объявите функции, не являющиеся членами, когда преобразование типов должно применяться ко всем параметрам» и Правило 46: «Определите в шаблонах функции, не являющиеся членами, когда требуется преобразование типов».

4
ответ дан 26 November 2019 в 22:08
поделиться

Во-первых: на самом деле два разных способа - это «перегрузка как элемент» и «перегрузка как не-член», а у последнего есть два разных способа напишите его (определение класса как друга внутри и определение класса вне класса). Называя их «внутри класса» и «вне класса» вы запутаетесь.


Перегрузки для + =, +, - =, - и т.д. имеют специальный шаблон:

struct Vector2 {
  float x, y;
  Vector2& operator+=(Vector2 const& other) {
    x += other.x;
    y += other.y;
    return *this;
  }
  Vector2& operator-=(Vector2 const& other) {
    x -= other.x;
    y -= other.y;
    return *this;
  }
};
Vector2 operator+(Vector2 a, Vector2 const& b) {
  // note 'a' is passed by value and thus copied
  a += b;
  return a;
}
Vector2 operator-(Vector2 a, Vector2 const& b) { return a -= b; } // compact

Этот шаблон позволяет преобразования, упомянутые в других ответах для аргумента LHS, при этом значительно упрощая реализацию. (Член или не член разрешает преобразования для RHS, когда он передается либо как const & , либо по значению, как и должно быть.) Конечно, это применимо только тогда, когда вы действительно хотите перегрузить оба + = и +, - = и - и т. д., но это все еще распространено.


Кроме того, иногда вы хотите объявить свою op +, не являющуюся членом, и т. Д. Как друзей в определении класса, используя трюк Бартона-Накмана , потому что из-за особенностей шаблонов и перегрузка, его нельзя найти иначе .

16
ответ дан 26 November 2019 в 22:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: