C++类和对象(3)

C++类和对象(3)

  • 运算符重载
    • 运算符重载注意事项
    • 一些不能重载的运算符
  • const成员函数
  • 初始化列表
  • 复制列表初始化自定义类型
    • 类型转换原理
    • 关键字explicit
  • 模板
    • 声明
    • 模板的注意事项

运算符重载

在重载流插入运算符中,如果将重载的函数放在类内,则会导致运算符方向相反。
C++类和对象(3)_第1张图片
这是什么原因呢?

运算符重载注意事项

  • 在运算符重载中,双目运算符的第一个参数一定要是运算符的左操作数,第二个参数一定要是右操作数
  • 在运算符重载中,若重载多个运算符,则要注意运算符的复用,如可以复用+= 重载 +,在复用过程中,要注意复用顺序不同可能导致不同的时间花费(主要是进行的构造函数的次数不同)
  • 在重载右不同含义的单目运算符,如++,–是,前置++,–没有参数,后置++,–有一个int类型的参数(C++规定)。

类中若不写赋值重载运算符,则默认会生成一个赋值重载运算符,该函数对内置类型之间赋值,自定义类型去调用自己的赋值重载运算符。
类中还会对取地址重载运算符生成2个默认函数,一个不是const成员函数,一个是const成员函数。

一些不能重载的运算符

C++存在一些不能重载的运算符。

1.作用域操作符: ::
2.条件操作符: ?:
3.点操作符: .
4.指向成员操作的指针操作符:->* , . *

const成员函数

C++类和对象(3)_第2张图片
在成员函数后加const,代表成员函数隐式传递的this指针被const修饰。
若下图print函数不加const,则会报错,因为权限扩大了。
在这里插入图片描述

初始化列表

初始化列表是用来初始化成员变量的,在C++中,栈帧开辟后会将栈帧初始化为随机值,所以在对象定义的时候,实际上已经被初始化为随机值了,这就导致如引用,被const修饰的成员,以及自定义类型,无法在构造函数修改(构造函数对成员进行的操作是赋值,同时无法访问其他类),所以需要引入初始化列表进行初始化,解决这个问题
C++类和对象(3)_第3张图片
同时,成员的缺省值所缺省的就是初始化列表,如果某个成员已被初始化列表初始化,则不需要走缺省值
初始化列表也有缺陷,如要开辟数组,则初始化列表就无法做到,所以最优的使用方法是初始化列表和构造函数一起使用,去长补短。

要注意,初始化列表初始化的顺序和成员声明顺序相同,所以在写初始化列表时,最好按声明顺序写初始化列表。

复制列表初始化自定义类型

在自定义类型初始化的时候,我们可以使用一个或多个内置类型进行初始化,前提是该自定义类型要有与参数对于的构造函数。

类型转换原理

任何类型转换,在底层都是开辟一块临时空间,用在暂存被转换的类型,然后在将临时空间赋值给变量。
C++类和对象(3)_第4张图片

将内置类型隐式转换成自定义类型,在1过程,调用自定义类型的构造函数,在2过程,调用自定义类型的拷贝构造。

关键字explicit

关键字explicit用来修饰构造函数,被修饰的构造函数无法通过复制列表的方式来调用构造函数。

模板

有些函数在使用的时候,内部逻辑是一样的,但是所传递的参数的类型是不一样的,对于这样的函数,C语言实现通常要写很多个不同的类型,但是引入模板后,就可以只写一份,大大提高了程序员的开发效率。

声明

模板的声明要使用templatetypename/class关键字,如图。
声明是语法 template,T1,T2是形参可以是任意字母。
C++类和对象(3)_第5张图片
在我们使用的时候,可以模板进行实例化,对于部分函数模板来说,其可以通过参数的类型来推到T的类型,从而进行隐式实例化,但作为类模板来说,就必须显示实例化。
C++类和对象(3)_第6张图片

模板的注意事项

关于模板类,模板函数和类模板,函数模板的区别。

1.类模板是模板,而模板类是类模板实例化后的类的名字,类模板实例化后依旧是抽象的。
2.函数模板是模板,而模板函数是函数模板实例化后的函数的名字。

综上,模板是不占用空间的,只有实例化后(类模板在实例化后)才会占用空间。
C++类和对象(3)_第7张图片

你可能感兴趣的:(C++从入门到精通,c++,java,jvm)