>"运算符的重载" /> >"运算符的重载 - 程序员文章站" />
欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C++ 流插入"<<"和流提取">>"运算符的重载

程序员文章站 2022-07-01 16:34:25
01 流插入 运算符重载的例子 还是以 类作为例子,假设想通过键盘的输入的内容,来初始化对象,则我们可以重载 类的流提取 运算符。 输入内容和输出内容: 04 小结 要想流插入 运算符能针对 自定义的对象 ,那么我们就需要 重载 针对该对象的 类的 运算符,并且只能 重载成全局的函数 ,然后在 类里 ......

01 流插入<<运算符的重载

c++ 在输出内容时,最常用的方式:

std::cout << 1 <<"hello";

问题:

  • 那这条语句为什么能成立呢?
  • cout 是什么?"<<" 运算符能用在 cout 上呢?

原因:

  • 实际上,cout 是在 iostream 头文件中定义的 ostream 类的对象。
  • "<<" 能够用在 cout 上是因为,在 ostream 类对 "<<" 进行了重载

对于std::cout << 1 <<"hello";这条语句,有可能按以下的方式重载成 ostream 类的成员函数:

ostream & ostream::operator<<(int n)
{
    .... // 输出n整型的代码
    return *this;
}

ostream & ostream::operator<<(const char * s)
{
    .... // 输出s字符串的代码
    return *this;
}
  • std::cout << 1;语句,等价于cout.operator<<(1);
  • std::cout << "hello";语句,等价于cout.operator<<("hello");
  • std::cout << 1 <<"hello";语句,等价于( cout.operator<<(1) ).operator<<("hello");

02 流插入<<运算符重载的例子

假定我们要想把某个对象里的内容进行打印输出,那么我们可以重载 ostream 类的流插入 << 运算符。

下面以 cstudent 类作为例子:

class cstudent // 学生类
{
public:
    // 构造函数
    cstudent(int id = 0, int age = 0, string name = ""):m_id(id), m_age(age), m_name(name) { }
    
    // 将该函数声明成友元函数
    // 目的是使得函数可以访问cstudent类的私有成员变量
    friend ostream & operator<<(ostream & o, const cstudent & s);
    
private:
    int m_age;      // 年龄
    int m_id;       // id号
    string m_name;  // 名字
};

// 重载ostream对象的流插入<<运算符函数
// 目的是使得能打印输出cstudent对象的信息
ostream & operator<<(ostream & o, const cstudent & s)
{
    o << s.m_id << "," << s.m_age << "," << s.m_name;
    return o;
}

int main()
{
    cstudent stu(1, 20, "小林coding");
    std::cout << stu ; // 输出std对象的全部信息
    
    return 0;
}

输出结果:

1,20,小林coding

需要注意是 ostream & operator<<(ostream & o, const cstudent & s) 函数是全局的,所以函数的第一个参数必须要传入 ostream 的对象,并且 cstudent 类需要将此函数声明成友元函数,使得函数可以访问 cstudent 类的私有成员变量。

03 流提取>>运算符重载的例子

还是以 cstudent 类作为例子,假设想通过键盘的输入的内容,来初始化对象,则我们可以重载 istream 类的流提取 >> 运算符。

class cstudent // 学生类
{
public:

    // 构造函数
    cstudent(int id = 0, int age = 0, string name = ""):m_id(id), m_age(age), m_name(name) { }
    
    // 将该函数声明成友元函数
    // 目的是使得函数可以访问cstudent类的私有成员变量
    friend ostream & operator<<(ostream & o, const cstudent & s);
    
    // 将该函数声明成友元函数
    // 目的是使得函数可以给cstudent类的私有成员变量进行赋值
    friend istream & operator>>(istream & is,  cstudent & s);
    
private:
    int m_age;      // 年龄
    int m_id;       // id号
    string m_name;  // 名字
};

// 重载ostream对象的流插入<<运算符函数
// 目的是使得能打印输出cstudent对象的信息
ostream & operator<<(ostream & o, const cstudent & s)
{
    o << s.m_id << "," << s.m_age << "," << s.m_name;
    return o;
}

// 重载istream对象的流提取>>运算符函数
// 目的是使得初始化cstudent对象的内容
istream & operator>>(istream & is,  cstudent & stu)
{
    string inputstr;
    is >> inputstr;
    
    int pos = inputstr.find(",", 0);         // 查找首次出现逗号的位置
    string tmpstr = inputstr.substr(0, pos); // 截取从0到pos位置的字符串
    stu.id = atoi(tmpstr.c_str());           // atoi可以将char*类型的内容转成int类型
    
    int pos2 = inputstr.find(",", pos + 1);            // 查找第二次出现逗号的位置
    tmpstr = inputstr.substr(pos + 1, pos2 - pos -1);  // 取出age的值
    stu.age = atoi(tmpstr.c_str());                    // atoi可以将char*类型的内容转成int类型
    
    tmpstr = inputstr.substr(pos2 + 1, inputstr.length() - pos2 - 1); // 取出name的值
    stu.name = tmpstr;
    
    return is;
}

int main()
{
    cstudent stu;
    
    // 将输入的信息,初始化stu对象
    cin << stu;
    
    // 输出std对象的信息
    cout >> stu;
    
    return 0;
}

输入内容和输出内容:

// 输入内容:
1,20,小林coding

// 输出内容:
1,20,小林coding

04 小结

要想流插入 << 运算符和流提取 >> 运算符能针对自定义的对象,那么我们就需要重载针对该对象的 ostream 类的 << 运算符 和 istream>> 运算符,并且只能重载成全局的函数,然后在 cstudent 类里需要把上面的两个重载函数声明成友元函数,使得两个重载的函数可以访问和赋值 cstudent 类里的私有成员函数。