zoukankan      html  css  js  c++  java
  • C++---使用类

    运算符重载

    概念

    • 运算符重载就是想法转换, 目的是简化函数调用的方式
    • 重载就是赋予新的含义, 运算符重载也是, 即同一个运算符可以有不同的功能
    • C++本身已经对一些运算符进行了重载, 同时C++允许程序员自己重载运算符
      • +号可以对不同类型(int float)的数据进行加法操作
      • << 既是移位运算符, 又可以配合cout向控制台输出数据
    • 定义一个运算符重载就像定义一个函数一样, 只不过这个函数名称以operator关键字开头
      • 返回类型 operator被重载的运算符(参数列表)

    可以重载的运算符

    运算符
    关系运算符 == != < > <= >=
    逻辑运算符 || && !
    一元运算符 + - * & ++ --
    位运算符 | & ~ ^ << >>
    赋值运算符 = += -= *= /= %= &= |= ^= <<= >>=
    内存声明与释放 new delete new[] delete[]
    其他运算符 函数调用() 成员访问 -> 成员指针访问 ->* 逗号 , 下标 []

    不能重载的运算

    • 点运算符 .
    • 成员指针访问运算符 *
    • 域运算符 ::
    • 长度运算符 sizeof
    • 三元运算符 ? :

    注意

    • 重载不能修改运算变量的个数, 比如, 关系运算是二元运算, 重载后也必须有两个变量参数运算
    • 重载不能修改运算符的优先级别, 比如, 乘除优先于加减, 重载后这个优先级不会被修改
    • 重载不能修改运算顺序, 比如, 赋值运算是从右到左的, 重载后不能改变
    class Integer
    {
        public:
        	//构造函数
        	Integer(): m_num(0){}
        	Integer(int num): m_num(num){}
        
        	const Integer operator+(const Integer & other) const 
            {
                cout << "重载了+号运算符, 以实现两个Integer的对象的相加" << endl;
                return Integer(this->m_num + other.m_num);
            }
        private:
        	int m_num;
    }
    
    Integer num1(1024);
    Integer num2(20);
    Integer num3 = num1 + num2;   //编译器实际调用 num3 = num1.operator+(num2);
    

    const的作用

    • const修饰成员变量

      • 只有一个const时, 如果const位于*的左侧, 表示指针所指的数据是常量, 不能通过该指针修改实际数据

        const int num = 1024;
        num = 2048;   			//不合法
        
        //const在*号左侧, 表示指针所指向数据是常量
        const int * ptr1_num1 = &num1;
        int const * ptr2_num1 = &num;
        prt1_num = &num;		//合法, 可以指向其他内存单元
        *ptr_num1 = 1234;		//不合法, 不能修改所指向的数据
        
      • 只有一个const时, 如果const位于*的右侧, 表示指针本身是常量, 不能指向其他内存单元, 所指向的数据可以修改

        //const在*右侧, 表示指针本身是常量, 不能指向其他内存单元
        int * const ptr3_num1 = &num1;
        ptr3_num1 = ptr2_num;
        
      • 如果有两个const位于*的左右两侧, 表示指针和指针所指向的数据都不能修改

    • const修饰函数参数

      • const修饰引用时, 不能修改引用对象的任何成员, 可以保护传递的参数, 起到不copy对象的目的, 节省效率
    • const修饰返回值

      • 如果函数要返回局部对象, 直接返回这个对象即可, 不要返回这个对象的引用
      • 在可以返回对象, 也可以返回对象的引用时, 首选返回引用, 提高效率
    • const修饰函数,时, 说明函数不会修改成员变量的值

    友元函数

    • 对于很多运算符来说, 可以选择使用成员函数或非成员函数来实现运算符重载, 通常非成员函数就是友元函数, 这样可以直接访问类的私有数据
    • 在定义运算符时, 不能同时选择这两种格式, 同时定义两种格式将被视为二义性错误, 出现编译错误

    建议准则:

    • C++规定, 赋值运算符=, 数组下标运算符[], 函数调用运算符(), 成员访问运算符->, 在重载时必须声明为类的成员函数

    • 一元运算符和复合赋值运算符重载时, 一般声明为类的成员函数

    • 流运算符<< >>, 类型转换运算符不能定义为类的成员函数, 只能是友元函数

    • 二元运算符在运算符重载时, 一般声明为友元函数

    firend ostream& operator<<(ostream& out, const Hero& hero);
        
    firend ostream& operator<<(ostream& out, const Hero& hero)
    {
        out << "昵称" << hero.GetNickName() << '
    ';
        out << "等级" << hero.GetLevel() << '
    ';
        return out;
    }
    

    赋值/拷贝构造函数

    • 简单的类, 默认拷贝构造函数一般就构用, 不需要显式地定义一个功能类似的拷贝构造函数

    • 当类拥有其他资源时, 如动态分配的内存, 打开的文件, 指向其他数据的指针, 网络连接等, 默认拷贝构造函数就不能拷贝这些资源, 必须显式地定义拷贝构造函数, 以完整地拷贝对象的所有数据

    • 为类定义赋值/拷贝构造函数, 即以对象为参数的构造函数

      Student::Student(Student & stu_ptr)
          
      //const关键字可以保证复制过程中不会改变被复制的对象
      Student::Student(const Student & stu_ptr)
      
    • 下面三张场景会调用复制构造函数

      • 当类的对象被初始化为同一类的另一个对象时
      • 当对象被作为参数传递给一个函数时
      • 当函数返回一个对象时

    类型转换

    • C++中, 存在隐式类型转换语法, 即自动类型转换

      int a = 12;
      a = 22.9 + a;
      
    • C++还提供了显式类型转换语法, 即强制类型转换

      int num = int(89.3);
      
    • C语言中,采用以下语法

      int num = (int)89.3;
      
    • 注意

      • 将浮点型数据赋值给整型变量时, 会舍弃小数部分
      • 将整型数据赋值给浮点型变量时, 数值不变, 但是会以指数形式存储
      • 将double性数据赋值给float型变量时, 注意数值范围溢出
      • 字符型数据可以赋值给整型变量, 存入的是字符的ASCII码
      • 将一个int, short或long型赋值给char类型变量时, 只将低8位传给char变量
      • 将有符号型数据赋值给长度相同的无符号型变量时, 连同原来的符号位一起传送
    • C++允许自定义类型之间转换, 但是自定义的类型转换规则只能以类的成员函数的形式出现

    • 将其他类型转换为当前类的类型时, 需要借助转换构造函数

    再谈构造函数

    • 构造函数是在创建对象时, 初始化对象
    • 编译会根据传递的实参来匹配不同的构造函数
    //无参构造
    Rectangle();
    
    Rectangle rect1();
    
    //带参构造
    Rectangle(float width, float height);
    
    Rectangle rect2(20, 30);
    
    //拷贝构造, 以拷贝的方式初始化对象时调用
    Rectangle(const Rectangle& rect);
    
    Rectangle rect3(rect2);
    
    //转换构造, 将其他类型转换为当前类型时调用
    Rectangle(float width);
    
    Rectangle rect4(99.8);
    Rectangle rect5 = 66.6;
    Rectangle rect6;
    rect6 = rect5 + 'A' + false;   //将char, bool都转换为Rectangle类型再运算
    
    • 当前类的类型转换为其他类型时, 使用类型转换函数

    • 类型转换函数只能以成员函数的形式出现, 也就是只能出现在类中

      //类型转换函数的语法格式
      operator type()
      {
          return data;
      }
      
      /*
      type可以是内置类型, 类类型以及由typedef定义的类型别名, 任何作为函数返回类型的类型都是被支持的, void除外, 且不允许转换为数组或函数类型, 可以转换为指针或引用类型
      */
      
    • 类型转换函数看起来没有返回值类型, 但其实隐式地指明了返回值类型

    • 类型转换函数也没有参数, 因为要将当前类的对象转换为其他类型, 编译器实际上会把当前对象的地址赋值给this指针, 这样就可以在函数体内可以操作当前对象

      operator float() const{
          return this->width;
      }
      
      //类型转换函数一般不会更改被转换的对象, 所以通常被定义为const
      //类型转换函数可以被继承, 可以是虚函数
      
  • 相关阅读:
    手机号码正则表达式
    POJ 3233 Matrix Power Series 矩阵快速幂
    UVA 11468
    UVA 1449
    HDU 2896 病毒侵袭 AC自动机
    HDU 3065 病毒侵袭持续中 AC自动机
    HDU 2222 Keywords Search AC自动机
    POJ 3461 Oulipo KMP模板题
    POJ 1226 Substrings KMP
    UVA 1455 Kingdom 线段树+并查集
  • 原文地址:https://www.cnblogs.com/KX-Lau/p/12857601.html
Copyright © 2011-2022 走看看