Работает ли оператор перегрузки << внутри класса? - PullRequest
7 голосов
/ 19 февраля 2012

Я имею в виду, я пытался перегрузить оператор << внутри класса </p>

как это

 class A {
      public:
           ostream &operator<<(ostream &os);// which doesnt work

      private:
           friend ostream &operator<<(ostream &os, const A& a); //Works
           int i;

 };

  Definition
          ostream &operator<<(ostream &os, const A& a) {
              os<<a.i;
              return os;
          }

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

Ответы [ 3 ]

19 голосов
/ 19 февраля 2012

Функция-член:

ostream &operator<<(ostream &os);

работает , но не для нужной вам ситуации.Он будет вызван, когда вы сделаете что-то вроде:

A a;
a << std::cout;

т.е. когда объект находится слева от оператора.

18 голосов
/ 19 февраля 2012

Проблема в том, что ваш operator<< будет принимать ostream в качестве второго параметра, а не первого.Таким образом, вы могли бы сделать myObject << std::cout, но это выглядело бы не интуитивно, и вы не смогли бы связывать вызовы из-за левой ассоциативности operator<<.

Еще одно преимущество объявления оператора как другаВ отличие от функции-члена, автоматические преобразования могут происходить.Это означает, что если у вас есть класс B, который не является производным от A, но имеет конструктор B(A const&), вы все равно сможете выполнить std::cout << my_b; и преобразовать его в A, а затемнапечатано.

К счастью, определение operator<< как друга может быть сделано в классе, если вы предпочитаете.Ваш код может быть записан как

class A {
    int i;
    friend std::ostream& operator<<(std::ostream& o, A const& a) {
        o << a.i;
        return o;
    }
};

Почему стандарт не позволяет вам указывать, на какую сторону должен идти аргумент?Давайте представим, что это так, и добавим ключевые слова left_of и right_of, чтобы указать:

struct B;

struct A {
     A left_of operator+(B const&) {
         return *this;
     }
};

struct B {
     B right_of operator+(A const&) {
         return *this;
     }
};

Что происходит сейчас, когда мы делаем A a; B b; f(a + b);?У каждого класса есть оператор, который обрабатывает этот случай, что означает, что мы не можем решить.В любом случае, видеть, как многие операторы должны дружить из-за возможностей конвертации, не допускать такого рода вещей - не такая уж большая проблема, и предотвращает подобные двусмысленности(Конечно, вы также можете определить оператор-член и свободный оператор, который вызовет очень похожую проблему.)

Кстати, определение вашего friend operator<< не возвращаетсявсе, что испортит цепочку.

1 голос
/ 03 апреля 2018

Помните, что для нестатической функции-члена класса первым аргументом является этот указатель.Таким образом, подпись вашей функции "operator <<" после компиляции станет: </p>

ostream &operator<<(A *this, ostream &os);

Это будет работать, когда вы сделаете что-то вроде:

A obj;
obj << std::cout;

Подумайте об "obj"в качестве первого аргумента и "std :: cout" в качестве 2-го аргумента оператора "<<". </p>

Лучший способ перегрузить "<<" - использовать функцию друга, потому что таким образом вы можете сделать свой перегруженный операторассоциативно. </p>

...