chapter12_使类对象像一个数值一样工作

  1. 一般来说,类的“三位一体”原则:构造函数、复制构造函数、析构函数、赋值运算符函数。

    如果一个类不需要显式定义析构函数(析构函数什么都不需要干),那么它往往也不需要显式定义赋值构造函数和赋值运算符函数。

  2. 输入输出运算符重载

    1. 目标

      希望实现自定义类和基本类型一样,可以被 cin >> 和 cout <<

    2. 对于二元运算符,左操作数必然为函数的第一个参数,右操作数必然为函数的第二个参数,而 cin 和 cout 的第一个参数为 istream 和 ostream,所以肯定不能是自定义类的成员函数,要把它们实现在外部

       class Str;
      
       std::istream& operator>>(std::istream& is, Str& str);
       std::ostream& operator<<(std::ostream& os, const Str& str);
      
       class Str {
           ...
       }
      
    3. 输出运算符重载

       std::ostream &operator<<(std::ostream &os, const Str &str) {
      
           for (Str::size_type i = 0; i < str.size(); i++) {
               os << str[i];
           }
      
           return os;
       }
      
    4. 输入运算符重载

       std::istream &operator>>(std::istream &is, Str &str) {
      
           str.data.clear();
      
           char c;
      
           while (is.get(c) && std::isspace(c));
      
           if (is) {
               do {
                   str.data.push_back(c);
               } while (is.get(c) && !std::isspace(c));
           }
      
           return is;
       }
      

    但是,输入运算符重载函数要读写 Str 类的private成员data,所以要使用友元函数

  3. 友元函数

    1. 友元函数不属于类的成员函数,放在外部,但是它拥有和成员函数一样的访问权利

    2. 友元函数随便放,一般放在类声明和public之间

       class Str {
           friend std::istream& operator>>(std::istream& is, Str& str);
      
           ...
       }
      
  4. 每次写运算符重载函数之前,都要想这样几个问题

    1. 这个运算符重载函数是否应该是一个类的成员函数

    2. 它有几个操作数?它的操作数是什么类型

    3. 应该返回什么类型的结果?

  5. std::string 到字符常量数组的转换

    1. s.c_str()

      生成一个指向一个’\0’结尾的字符数组的const char*的值。

      注:数组中的值只是短暂存在,下一次改变s的值的操作后就会失效。用户不能删除该数组的指针,也不应该使用该指针的一个复件,因为只是短暂存在

    2. s.data()

      和 s.c_str() 的唯一区别是,生成的数组不以 ‘\0’ 结尾

    3. s.copy(p, n)

      从 s 中拷贝 n 个字符到 p 所指向的内存块中,用户来保证p指针的内存足够容纳 n 个字符

发布了391 篇原创文章 · 获赞 7 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/captxb/article/details/103075626