2012-05-31 2 views
3

У меня есть класс Counter, и я хочу перегрузить operator <<, чтобы вывести элемент данных Counter. Я попытался сделать ostream перегружать функции-члена:Может ли перегрузка нагрузки быть членом функции?

Counter{ 
public: 
    std::ostream& operator<<(std::ostream& outStream, const Counter& c); 
private: 
    int count_; 
}; 

std::ostream& Counter::operator<<(std::ostream& outStream, const Counter& c){ 
    outStream << c.count_; 
    return outStream; 
} 

Но компилятор г ++ всегда выдает ту же ошибку:

‘std::ostream& Counter::operator<<(std::ostream&, const Counter&)’ must take exactly one argument

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

Counter{ 
public: 
    friend std::ostream& operator<<(std::ostream& outStream, const Counter& c); 
private: 
    int count_; 
}; 

std::ostream& operator<<(std::ostream& outStream, const Counter& c){ 
    outStream << c.count_; 
    return outStream; 
} 

Означает ли это, что перегрузка оператора поток не может быть функцией членом класса?

+5

Это не * есть *, чтобы быть другом - вы можете использовать открытый интерфейс, если ваш класс хорошо разработан ... – Flexo

+1

Он должен быть другом, если вы хотите получить доступ к непубличным членам, как и любой другой другая функция; ничего особенного о 'operator <<' здесь. – ildjarn

+0

@ildjarn, но может ли это быть функцией-членом? – Brian

ответ

2

Если вы разместите оператор ostream в самом классе, то он не будет работать так, как вы ожидаете. Это будет функция-член, означающая его вызывать: вам нужно было бы это сделать: c.operator<<("output"), что явно не то, что вы хотите сделать. Чтобы он работал так, как вы ожидаете, оператор ostream должен находиться вне класса. Вы можете сделать это, сделав его другом или просто поместите его вне класса и используйте getters (accessors) для вывода данных.

+0

Инфиксная нотация работает отлично для операторов-членов ... но отправка производится на основе левого операнда. –

+0

Я вроде понимаю, что здесь происходит, спасибо ~ – Brian

2

Добавьте метод public запроса, который возвращает значение count_, то он не должен быть friend:

Counter{ 
public: 
    int count() const { return count_; } 
private: 
    int count_; 
}; 

std::ostream& operator<<(std::ostream& outStream, const Counter& c){ 
    outStream << c.count(); 
    return outStream; 
} 
+0

Я имею в виду ..может 'operator <<' быть членом функции Counter? – Brian

+0

Нарушение внутренних элементов - плохая идея (это вызывает чрезмерную связь с другими фрагментами кода). Было бы лучше предоставить метод 'print()', который берет поток в качестве параметра, а затем позволяет сериализовать объект. –

+0

@LokiAstari, внутренние элементы здесь не отображаются. – hmjd

2

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

+0

спасибо. Это имеет смысл быть мной. – Brian

0

К сожалению, полезные перегрузки для операторов потокового вывода (< <) не могут быть членами класса, так как ostream & должен быть слева и использоваться. Им не нужно быть друзьями класса, который вы хотите передать, если им не нужен доступ к защищенным или закрытым членам. Это означает, что если вы можете реализовать оператор потоковой передачи, используя только публичные функции, такие как наблюдатели/аксессоры, не объявляя его другом.

В вашем первом классе Counter вы объявляете функцию-член класса, которая кажется недействительной. Во втором примере класса Counter вы заявляете, что ваша операционная перегрузка для < <, которая кажется действительной, имеет доступ к закрытым членам. Во втором примере функция должна быть объявлена ​​вне класса.

Википедия Operators in C and C++ имеет хороший список возможных перегрузок операторов, в том числе в классах < < перегрузки, даже если они не очень полезны. Перегруженные в классе перегрузки должны быть вызваны назад CounterInstance << cout;, что является нелогичным.

+0

спасибо, очень полезно – Brian

Смежные вопросы