2012-06-27 2 views
0

Я написал эту простую программу для перегрузки.Перегрузка оператора << в C++

Это мой код:

#include <iostream> 
#include <string> 
using namespace std; 

class sex_t 
{ 
    private: 
     char __sex__; 

    public: 
     sex_t(char sex_v = 'M'):__sex__(sex_v) 
     { 
      if (sex_v != 'M' && sex_v != 'F') 
      { 
       cerr << "Sex type error!" << sex_v << endl; 
       __sex__ = 'M'; 
      } 
     } 

     const ostream& operator << (const ostream& stream) 
     { 
      if (__sex__ == 'M') 
       cout << "Male"; 
      else 
       cout << "Female"; 
      return stream; 
     } 
}; 

int main(int argc, char *argv[]) 
{ 
    sex_t me('M'); 
    cout << me << endl; 
    return 0; 
} 

Когда я скомпилировать его, распечатать много сообщений об ошибках:

Сообщение об ошибке была в беспорядке.

Мне слишком сложно найти полезное сообщение.

sex.cpp: 在函数‘int main(int, char**)’中: 
sex.cpp:32:10: 错误: ‘operator<<’在‘std::cout << me’中没有匹配 
sex.cpp:32:10: 附注: 备选是: 
/usr/include/c++/4.6/ostream:110:7: 附注: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostre 
+2

'cerr <<" Ошибка типа пола! " << sex_v' Вы правы, я никогда не слышал об этой позиции. – chris

+1

При всей серьезности одна вещь, которую вы НЕ должны делать, - это использовать два ведущих подчеркивания. Это зарезервировано для реализации. – chris

+0

Что мне делать? использовать '_sex_' ИЛИ другое? – thlgood

ответ

1

При перегрузке для потоков вы объявить оператору < < глобально и/или как friend (с преимуществами) для вашего класса, чтобы он мог получить доступ к своим «частным членам» (ooh ...). Вы можете объявить friend внутри класса, чтобы объявить его глобально. Не используйте const на потоках.

Далее, используйте переданный поток в вашей перегрузке. В вашем методе вы используете cout, когда вы использовали его в любом случае, просто используя аргумент stream.

Я не проверял это, но вижу, работает ли оно для вас.

class sex_t 
{ 
private: 
    char __sex__; 
public: 
    sex_t(char sex_v = 'M'):__sex__(sex_v) 
    { 
     if (sex_v != 'M' && sex_v != 'F') 
     { 
      cerr << "Sex type error!" << sex_v << endl; 
      __sex__ = 'M'; 
     } 
    } 

    friend ostream& operator << (ostream& stream, sex_t& sex); 
}; 


ostream& operator << (ostream& stream, sex_t& sex) 
{ 
    if (__sex__ == 'M') 
     stream << "Male"; 
    else 
     stream << "Female"; 
    return stream; 
} 
+0

что лучше? друга 'operator <<' или определения функции 'getSex()' в 'sex_t'? – shengy

+0

@shengy, 'operator <<' идеально подходит, если пользователь будет иметь возможность распечатать его. – chris

+0

@chris Я имею в виду функцию 'friend operator <<' или функцию 'non-friend <<' function :) – shengy

4

Аргумент и возврат от operator<< являются неконстантными. Также он должен быть нечленом - вы написали перегрузку для me << cout, а не cout << me. Кроме того, идентификаторы, содержащие два символа подчеркивания, зарезервированы для реализации, а их использование - неопределенное поведение.

+0

+1; Короче и точно. –

3

«C++ Primer четвёртое издание» Глава 14 раздела 14.2 Входные и выходные Операторы:

IO операторы должны быть не входящими в функции, мы не можем сделать оператор членом нашего класса. Если бы мы сделали, то левый операнд должен быть объектом нашего класса типа:

// if operator<< is a member of Sales_item 
    Sales_item item; 
    item << cout; 

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

// general skeleton of the overloaded output operator 
    ostream& 
    operator <<(ostream& os, const ClassType &object) 
    { 
     // any special logic to prepare object 

     // actual output of members 
     os << // ... 

     // return ostream object 
     return os; 
    } 

Первый параметр является ссылкой к объекту ostream, на котором будет генерироваться вывод. Ostream не является константой, потому что запись в поток изменяет свое состояние. Параметр является ссылкой, потому что мы не можем скопировать объект ostream.

Второй параметр обычно должен быть ссылкой на константу типа типа, который мы хотим напечатать. Параметр является ссылкой, чтобы избежать копирования аргумента. Он может быть const, потому что (обычно) печать объекта не должна его изменять. Сделав параметр const ссылкой, мы можем использовать одно определение для печати объектов const и nonconst.

Обратный тип - это ссылка на поток. Его значение обычно является объектом ostream, против которого применяется оператор вывода.

EDIT:

Я попытался изменить свой код, и если вы используете __sex__ в sex_t «частного члена s, вы должны написать еще get function, чтобы получить„M“или„F“, и если вы вызовите его в своей функции operator<<, вы, вероятно, получите сообщение об ошибке, потому что ссылка const может вызывать только функцию const, поэтому вы должны сделать свою get function функцией const, только для напоминания :)

+0

Еще одно преимущество использования ссылки * const * заключается в том, что вы можете сделать что-то вроде этого: 'std :: cout << sex_t ('M');', который не может связываться с неконстантной ссылкой. – chris

+0

@chris Да :) Я чуть не забыл, что – shengy

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