Почему друг функция предпочтен функции членства для оператора <<

Когда Вы собираетесь распечатать объект, друг, оператор <<используется. Мы можем использовать функцию членства для оператора <<?

class A {

public:
void operator<<(ostream& i) { i<<"Member function";}
friend ostream& operator<<(ostream& i, A& a) { i<<"operator<<"; return i;}
};


int main () {

   A a;
   A b;
   A c;
   cout<<a<<b<<c<<endl;
   a<<cout;
  return 0;
}

Одна точка - то, что друг функция позволяет нам использовать его как это

cout<<a<<b<<c

Что другие причины?

5
задан skydoor 16 March 2010 в 21:57
поделиться

4 ответа

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

Для операторов выходного потока левая часть всегда является объектом потока, поэтому если вы передаете поток в стандартный класс, а не пишете поток сами, то вам придется предоставить свободную функцию, а не член вашего класса.

Хотя можно было бы предоставить оператор обратного потока как функцию-член и передавать поток вот так:

myObject >> std::cout;

мало того, что вы нарушите очень сильное библиотечное соглашение, как вы указали, цепочка операций вывода не будет работать из-за группировки слева направо >>.

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

11
ответ дан 18 December 2019 в 07:08
поделиться

У вас нет выбора - это должна быть свободная функция.

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

template <class A, class B>
std::ostream& operator<<(std::ostream& os, const std::pair<A, B>& p)
{
  return os << '(' << p.first << ", " << p.second << ')';
}

Нет необходимости, чтобы она была дружественной, поскольку first и second доступны публично.

10
ответ дан 18 December 2019 в 07:08
поделиться

Вы не можете. Но если вы не хотите, чтобы это была функция friend, сделайте ее свободной функцией и реализуйте ее в терминах публичного интерфейса класса. Например,

 ostream& operator<<(ostream& os, Myclass& obj)
{
   return obj.print(os);
}

ostream& MyClass::print(ostream& os)
{
   os << val; // for example.
   return os;
}
0
ответ дан 18 December 2019 в 07:08
поделиться

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

Почему вы предпочитаете определять его в классе? Иногда приятно определять все операторы вместе:

struct SomeClass {
    // blah blah blah
    SomeClass &operator+=(const SomeClass &rhs) {
        // do something
    }
    friend SomeClass operator+(SomeClass lhs, const SomeClass &rhs) {
        lhs += rhs;
        return lhs;
    }
    // blah blah blah
    // several pages later
};

может быть немного более удобным для пользователя, чем:

struct SomeClass {
    // blah blah blah
    SomeClass &operator+=(const SomeClass &rhs) {
        // do something
    }
    // blah blah blah
    // several pages later
};

SomeClass operator+(SomeClass lhs, const SomeClass &rhs) {
    lhs += rhs;
    return lhs;
}

Это, конечно, предполагает, что вы определяете связанные функции-члены в определении класса, а не объявляете их там и определяете их в файле .cpp.

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

1
ответ дан 18 December 2019 в 07:08
поделиться
Другие вопросы по тегам:

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