C++体验之“三”——运算符重载、静态成员、const类型成员、内联函数

——————一、运算符重载———————

1、概念:重载运算符是具有特殊函数名的函数,关键字operator后面接需要定义的操作运算符。操作符重载也是一个函数,具有返回值和形参表,他的形参数目与操作符的操作数数目相同,使用运算符重载可以提高代码的可读性

   // 当前日期days天后是什么日期? 
    Date operator+(int days)
    {
        Date tmp(*this);
        tmp._day += days;
        return tmp;
    }

    // 当前日期days天前是什么日期? 
    Date operator-(int days)
    {
        Date tmp(*this);
        tmp._day -= days;
        return tmp;
    }

    // 两个日期之间差了多少天? 
    Date operator-(const Date& d)
    {
        int flag = 1;
        Date max = *this;
        Date min = d;
        if (*this<d)
        {
            max = d;
            min = *this;
            flag = -1;
        }
        int count = 0;
        while (min != max)
        {
            ++min;
            count++;
        }
        return count*flag;
    }

    // 日期比大小 
    bool operator>(const Date& d)
    {
        return (_year > d._year || (_year == d._year && _month > d._month) ||
            (_year == d._year && _month == d._month &&  _day > d._day));
    }

    bool operator<(const Date& d)
    {
        return !((*this > d) || (*this == d));
    }

    bool operator==(const Date& d)
    {
        return (_year == d._year && _month == d._month && _day == d._year);
    }

    bool operator!=(const Date& d)
    {
        return !(*this == d);
    }

    Date& operator=(const Date& d)//赋值运算符
    {
        if (this != &d)
        {
            _year = d._year;
            _month = d._month;
            _day = d._day;
        }
        return *this;
    }

    // 重载取地址符号 
    Date* operator&()
    {
        return this;
    }

    // 前置++ 
    Date& operator++()
    {
        _day += 1;
        return *this;
    }

    // 后置++ 
    Date operator++(int)
    {
        Date tmp(*this);//保存+1之前的旧值
        _day += 1;
        return tmp;
    }

    // 前置-- 
    Date& operator--()
    {
        _day -= 1;
        return *this;
    }

    // 后置--
    Date operator--(int)
    {
        Date tmp(*this);//保存-1之前的旧值
        _day -= 1;
        return tmp;
    }

2、注意:
(1)不能通过连接其他符号来创建新的操作符:比如operator@
(2)重载操作符必须有一个类类型或者枚举类型的操作数
(3)用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不能改变其含义
(4)作为类成员的重载函数,其形参看起来比操作数数目少1成员函数的操作符有一个默认的形参this,限定为第一个形参
(5)一般将算术操作符定义为非成员函数,将赋值运算符定义成员函数
(6)操作符定义为非类的成员函数时,一般将其定义为类的友元
(7)== 和 != 操作符一般要成对重载
(8)下标操作符[]:一个非const成员并返回引用,一个是const成员并返回引用
(9)解引用操作符*和->操作符,不显示任何参数
(10)前置式++/–必须返回被增量或者减量的引用,后缀式操作符必须返回旧值,并且应该是值返回而不是引用返回
(11)输入操作符>>和输出操作符<<必须定义为类的友元函数

——————二、静态成员————————

1、概念:声明为static的类成员(成员数据或成员函数)称为类的静态成员(静态成员函数没有this指针)

class test{
public:
      test(){}
     ~test(){}
public:
    //静态成员函数
    static int getCount(){
        return m_nCount;
    }
private:
    //静态数据成员
    static int m_nCount;
};

2、特性:
(1)静态成员为所有类对象所共享,不属于某个具体的实例
(2)类静态成员即可用类名::静态成员或者对象.静态成员来访问
(3)类静态成员变量必须在类外定义,定义时不添加static关键字
(4)类的静态成员函数没有默认的this指针,因此在它里面不能使用任何非静态成员
(5)静态成员和类的普通成员一样,也有public、protected、private3种访问级别,也可以具有返回值,const修饰符等参数
提醒:静态成员函数可以调用非静态成员函数吗?——答案是不可以哦
非静态成员函数可以调用类的静态成员函数吗?——答案是可以呢
3、静态变量和其他变量的区别:
(1)名称上的区别:成员变量也叫实例变量;静态变量也叫类变量。
(2)内存存储的区别:成员变量存储到堆内存的对象中,静态变量存储到方法区的静态区中。
(3)生命周期不同:

  1)成员变量随着对象的出现而出现,随着对象的消失而消失。
  2)静态变量随着类的出现而出现,随着类的消失而消失。

4、补充:
(1)静态变量使用 static 修饰符进行声明;
(2)在类被实例化时创建,通过类进行访问不带有 static 修饰符声明的变量称做非静态变量;
(3)在对象被实例化时创建,通过对象进行访问;
(4)一个类的所有实例的同一静态变量都是同一个值,同一个类的不同实例的同一非静态变量可以是不同的值;
(5)静态函数的实现里不能使用非静态成员,如非静态变量、非静态函数等。

—————三、const类型成员———————

——在C++中,只有被声明为const的成员函数才能被一个const类对象调用。

——在C++中,若一个变量声明为const类型,则试图修改该变量的值的操作都被视编译错误。

——要声明一个const类型的类成员函数,只需要在成员函数参数列表后加上关键字const,

——在类体之外定义const成员函数时,还必须加上const关键字

——若将成员成员函数声明为const,则该函数不允许修改类的数据成员。

——const成员函数可以被具有相同参数列表的非const成员函数重载,

const使用场景
(1)const修饰形参,一般和引用同时使用
(2)const修饰返回值
(3)const修饰类数据成员,必须在构造函数的初始化列表中初始化
(4)const修饰类成员函数,实际修饰隐含的this,表示在类中不可以对类的任何成员进行修改
(5)在const修饰的成员函数中要对类的某个数据成员进行修改,该数据成员定义声明是必须加mutable关键字

小结:
1)const成员函数可以访问非const对象的非const数据成员、const数据成员,也可以访问const对象内的所有数据成员;
2)非const成员函数可以访问非const对象的非const数据成员、const数据成员,但不可以访问const对象的任意数据成员;

——————四、内联函数————————

1、概念:以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数压栈的开销,内联函数提升程序运行的效率
2、特性
(1)inline是一种以空间换时间的做法,省去调用函数额开销。所以代码很长或者有循环/递归的的函数不适宜使用内联
(2)inline对于编译器而言只是一个建议,编译器会自动优化,如果定义为inline的函数体内有循环/递归等等,编译器优化时会忽略掉内联
(3)inline必须函数定义放在一起,才能成为内联函数,仅将inline放在声明前是不起作用的
(4)定义在类内的成员函数默认定义为内联函数

——宏有什么优缺点?
优点——1)不要求类型;
2)可以将类型作为参数传过去;
3)执行速度比函数快,不需要调用,只占编译时间;
4)只是简单替换,不占用运行时间。
缺点——1)宏不能调试;
2)宏在某种程度上比较复杂,有些编译器限制宏只能定义成一行;
3)宏是直接替换,代码块不能太长;
4)宏不能递归。

——宏函数和内联函数的区别?
(1)内联函数在运行时可调试,而宏定义不可以;
(2)编译器会对内联函数的参数类型做安全检查或自动类型转换(同普通函数),而宏定义则不会;
(3)内联函数可以访问类的成员变量,宏定义则不能;
(4)在类中声明同时定义的成员函数,自动转化为内联函数。

注意:
在C++中,强制建议使用const代替宏常量,使用内联函数代替宏函数,
const和内联函数在进行编译时不仅进行替换,而且还会进行参数类型检
测,提高了程序的安全性。内敛函数可以是普通函数,也可以是类的成员
函数;函数式宏不能作为类的成员函数
这里写图片描述

猜你喜欢

转载自blog.csdn.net/paranoid_cc/article/details/80737396