重载自定义类集的提取操作符

Overloading extraction operator for a custom class set

本文关键字:提取 操作符 自定义 重载      更新时间:2023-10-16

我做了一个自定义类user,并在另一个类dbase中做了一个set<user> users。我已经成功地重载了类user的提取操作符,现在我正试图重载类dbase的提取操作符。

这是我的代码:

ostream& operator<< (ostream &out, dbase &db) {
    set<user>::iterator it;
    for(it=db.users.begin(); it!=db.users.end(); it++)
        out<<(*it)<<endl;    //error reported on this line
    return out;
}

但是我一直得到这个错误:

error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'
这是user类的operator<<声明:
ostream& operator<<(ostream &out, user &u) {
    cout<<endl;
    cout<<"Username: "<<u.uname;
    cout<<endl;
    return out;
}
(ideone)
#include <iostream>
#include <set>
#include <string>
#include <sstream>
using namespace std;
template <class T>
string to_string(T x) {
    stringstream ss;
    ss<<x;
    return ss.str();
}
class date {
    int dd,mm,yyyy;
    string str_date;
    public:
        string get_date() {
            return to_string(dd)+"-"+to_string(mm)+"-"+to_string(yyyy);
        }
        friend ostream& operator << (ostream&,date&);
        friend istream& operator >> (istream&,date&);
};
ostream& operator<< (ostream &out, date &d) {
    out<<d.get_date();
    return out;
}
istream& operator>> (istream &in, date &d) {
    cin>>d.dd>>d.mm>>d.yyyy;
    return in;
}
class user {
    string uname, pwd;
    string full_name, contact;
    static unsigned long long int id;
    date dob;
    public:
        bool operator < (const user &u) const {
            if(uname.compare(u.uname)<0) return true;
            return false;
        }
        void set_uname(string u) {
            uname = u;
        }
        void set_attrib() {
            string temp_pass;
            while(1) {
                cout<<"Full Name: ";
                cin>>full_name;
                cout<<"Password: ";
                cin>>temp_pass;
                cout<<"Confirm Password: ";
                cin>>pwd;
                if(pwd.compare(temp_pass))
                    cout<<"Passwords do not match. Try Again."<<endl;
                else break;
            }
            cout<<"Contact Number: ";
            cin>>contact;
            cout<<"Date of Birth(dd mm yyyy): ";
            cin>>dob;
        }
        friend ostream& operator<<(ostream&, user&);
};
ostream& operator<<(ostream &out, user &u) {
    cout<<endl;
    cout<<"Username: "<<u.uname;
    cout<<endl;
    return out;
}
class dbase {
    set<user> users;
    public:
        void add_user() {
            string uname;
            user u;
            while(1) {
                cout<<"Username: ";
                cin>>uname;
                u.set_uname(uname);
                if(users.find(u)==users.end()) {
                    u.set_uname(uname);
                    u.set_attrib();
                    users.insert(u);
                    break;
                }
                else
                    cout<<"Username already exists. Please try a different username."<<endl;
            }
        }
        friend ostream& operator << (ostream&, dbase&);
};
ostream& operator<< (ostream &out, dbase &db) {
    set<user>::iterator it;
    user u;
    for(it=db.users.begin(); it!=db.users.end(); it++)
        out<<(*it)<<endl;
    return out;
}
int main() {
    return 0;
}

So…

<标题>第一课

请张贴一个完整的可编译的例子。在这种情况下,你没有提供足够的信息让我们容易地调试你的代码。

对于您的特定问题,代码可能看起来像这样:

#include <iostream>
#include <set>
using namespace std;
class user {
    public:
        user(int id = 0): id(id) {}
        int id;
};
class dbase {
    public:
        set<user> users;
};
bool operator<(user const & lhs, user const & rhs) {
    return lhs.id < rhs.id;
}
ostream& operator<< (ostream &out, user & user) {
    return out << "user(" << user.id << ")";
}
ostream& operator<< (ostream &out, dbase &db) {
    set<user>::iterator it;
    user u;
    for(it=db.users.begin(); it!=db.users.end(); it++)
        cout<<*it<<endl;
    return out;
}
int main() {
    dbase db;
    db.users.emplace(3);
    db.users.emplace(4);
    cout << db << endl;
}
<标题>课2 h1> 发布编译器报告的整个错误消息。在本例中,它实际上是:
se.cc: In function ‘std::ostream& operator<<(std::ostream&, dbase&)’:
se.cc:28:16: error: cannot bind ‘std::ostream {aka std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’
         cout<<*it<<endl;
                ^
In file included from /opt/gcc/4.8.1/include/c++/4.8.1/iostream:39:0,
                 from se.cc:1:
/opt/gcc/4.8.1/include/c++/4.8.1/ostream:602:5: error:   initializing argument 1 of ‘std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = user]’
     operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
     ^

注意,我没有以任何方式编辑错误消息。你可能遗漏了其他信息,而这些信息可能对试图回答你问题的人有帮助。

<标题> 3 课

代替:

ostream& operator<< (ostream &out, user & user) { ... }

:

ostream& operator<< (ostream &out, user const & user) { ... }
<标题>课4

当重载流提取操作符或流插入操作符时,可能永远不应该使用coutcerr。相反,您将一个流对象传递给函数。在您的示例中,您使用典型的(预期的)参数名称out来命名它。

所以,你的两个流插入操作符应该将cout的每个实例替换为out

这将使你的代码正确地工作,当你扩展它来使用诸如使用fstream将用户数据库写入文件,或者如果你想打印消息到cerr

<标题>课5

提醒一下。这是一个问题,因为*it返回对const User的引用。所以你现有的operator<<重载不匹配,因为它想要一个非const版本的User。