• 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
      //类型转换函数可以被继承, 可以是虚函数
      
  • 相关阅读:
    WebFlux系列(二) Server-Sent Events
    WebFlux系列(一)HelloWorld
    Reactor系列(十九)StepVerifier测试
    C++中vector和set使用sort方法排序
    获取线程ID
    C标准中一些预定义的宏__DATE__ __FILE__ __LINE__ __TIME__ __func__
    opencv测试代码
    nohub相关
    tensorflow相关练习
    摄像机相关
  • 原文地址:https://www.cnblogs.com/KX-Lau/p/12857601.html
Copyright © 2020-2023  润新知