类的六个默认成员函数、const、static用法


这里写图片描述


1.构造函数


构造函数概念

构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时,由编译器自动调用,在对象的生命周期内只调用一次,保证每个数据成员都有一个合适的初始值


构造函数特性

1.函数名与类名相同
2.没有返回值
3.新对象被创建时,由编译器自动调用,且在对象的生命周期内仅调用一次
4.构造函数可以重载,实参决定了调用哪个构造函数
5.无参构造函数和带有缺省值的构造函数都认为是缺省的构造函数,并且缺省的构造函数只能有一个
6.有初始化列表(可以不用)
7.如果没有显式定义时,编译器会合成一个默认的构造函数
8.构造函数不能用const修饰

const修饰的函数不能改变成员变量,而创建类对象时,构造函数要进行初始化(改变成员变量),故两个相矛盾,所以构造函数不能用const修饰

9.构造函数不能为虚函数

虚函数表vtbl,每一个拥有虚成员函数的类都有一个指向虚函数表的指针。对象通过虚函数表里存储的虚函数地址来调用虚函数。
那虚函数表指针是什么时候初始化的呢?
当然是构造函数。当我们通过new来创建一个对象的时候,第一步是申请需要的内存,第二步就是调用构造函数。试想,如果构造函数是虚函数,那必然需要通过vtbl来找到虚构造函数的入口地址,显然,我们申请的内存还没有做任何初始化,不可能有vtbl的。因此,构造函数不能是虚函数。

>


对象初始化

初始化列表:
以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个”成员变量”后面跟一个放在括号中的初始值或表达式

注意:
1.每个成员在初始化列表中只能出现一次
2.初始化列表仅用于初始化类的数据成员,并不指定这些数据成员的初始化顺序,数据成员在类中定义顺序就是在参数列表中的初始化顺序尽量避免使用成员初始化成员,成员的初始化顺序最好和成员的定义顺序保持一致

类中包含以下成员,一定要放在初始化列表位置进行初始化:
1.引用成员变量
2.const成员变量
3.类类型成员(该类有非缺省的构造函数)


构造函数作用

1.构造&初始化对象
2.类型转换

对于单个参数构造函数,可以将其接受参数转化成类类型对象。用explicit(explicit是表明该构造函数是显示的, 而非隐式的, 跟它相对应的另一个关键字是implicit, 意思是隐藏的,类构造函数默认情况下即声明为implicit(隐式))修饰构造函数,抑制由构造函数定义的隐式转换,explicit关键字类内部的构建声明上,在类的定义体外部的定义上不再重复。


2.拷贝构造函数


拷贝构造函数概念

只有单个形参,而且该形参是对本类类型对象的引用(常用const修饰),这样的构造函数称为拷贝构造函数。拷贝构造函数是特殊的构造函数,创建对象时使用已存在的同类对象来进行初始化,由编译器自动调用。


拷贝构造函数特征

构造函数的重载,构造函数的性质拷贝构造函数均满足
参数必须使用类类型对象引用传递

如果不用引用,传参过程会生成临时变量,临时变量的创建需要调用拷贝构造,调拷贝是传值,那又要需要生成临时变量…..(无限递归,崩溃)

如果没有显式定义,系统会自动合成一个默认的拷贝构造函数(底层看情况选择合适的方法实现拷贝构造,可能是直接赋值)。默认的拷贝构造函数会依次拷贝类的数据成员完成初始化


拷贝构造函数使用场景

1.对象实例化对象
2.作为函数参数
3.作为函数返回值(效率高)


3. 析构函数

(不能重载)


概念

与构造函数功能相反,在对象被销毁时,由编译器自动调用,完成类的一些资源清理和汕尾工作


特性

1.析构函数在类名(即构造函数名)加上字符~
2.析构函数无参数无返回值
3.一个类有且只有一个析构函数。若未显示定义,系统会自动生成缺省的析构函数
4.对象生命周期结束时,C++编译系统系统自动调用析构函数
5.注意析构函数体内并不是删除对象,而是做一些清理工作


4.赋值运算符重载


5.取地址操作符重载


运算符重载


运算符重载概念

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


这里写图片描述


这里写图片描述


注意事项

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


6.const修饰的取地址操作符重载


const修饰类成员


const使用场景

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


const


//const 修饰变量

const int *p = &a;(所指内容不能改变)
//表示指针所指数据是常量,不能通过解引用修改数据
//指针本身是变量,可以指向其他的内存单元
int* const p = &a; (指向不能改变)
//表示指针本身是常量,不能指向其他内存地址
//指针所指的数据可以通过解引用修改


//const 修饰函数
void Fun(const int a)
// 形参不能被改变
void Fun(int a)const
//const修饰的成员函数不能修改任何的成员变量
//(mutable修饰的变量除外)

const用法


  1. const对象可以调用非const成员函数(不可以)和const成员函数(可以)吗?
    如果非const成员函数里边修改类内成员,const调用后就会引起矛盾
  2. 非const对象可以调用非const成员函数(可以)和const成员函数(可以)吗?
    可以
  3. const成员函数内可以调用其它的const成员函数(可以)和非const成员函数(不可以)吗?

  4. 非const成员函数内可以调用其它的const成员函数(可以)和非const成员函数(可以)吗?
    如果说非const(可读可写)所管辖范围大,const(只读)范围小,把调用比作包含就可以理解啦


静态成员


定义

声明为static的类成员(成员数据或成员函数)称为类的静态成员


特性

1.静态成员为所有类对象所共享,不属于某个具体的实例
2.类静态成员即可用类名::静态成员或者对象.静态成员来访问
3.类静态成员变量必须在类外定义,定义时不添加static关键字
4.类的静态成员函数没有默认的this指针,因此在它里面不能使用任何非静态成员
5.静态成员和类的普通成员一样,也有public、protected、private,3种访问级别,也可以具有返回值,const修饰符等参数


注意事项

  1. 静态成员函数可以调用非静态成员函数吗?
    可以
  2. 非静态成员函数可以调用类的静态成员函数吗?
    不行

static

1.局部静态变量

static存储空间在静态常量区,(普通变量在栈上),static修饰的变量生命周期长。且在定义时应该初始化(没有初始化,不开辟空间,只是声明,使用时才开辟)。static局部变量具有”记忆性”与生存期的”全局性”

2.外部静态变量/函数

用来表示不能被其它文件访问的全局变量和函数。为了限制全局变量/函数的作用域, 函数或变量前加static使得函数成为静态函数。

3.静态数据成员/成员函数(C++独有,C不具有)

表示属于一个类而不是属于此类的任何特定对象的变量和函数. 这是与普通成员函数的最大区别, 也是其应用所在, 比如在对某一个类的对象进行计数时, 计数生成多少个类的实例, 就可以用到静态数据成员. 在这里面, static既不是限定作用域的, 也不是扩展生存期的作用, 而是指示变量/函数在此类中的唯一性. 这也是”属于一个类而不是属于此类的任何特定对象的变量和函数”的含义.
(static类内定义变量,不占类内空间,只是声明,类外需要定义带作用域)


static用法


猜你喜欢

转载自blog.csdn.net/Romantic_C/article/details/81487133