> 文章列表 > 【C++】构造函数,析构函数,拷贝构造,运算符重载,const 成员

【C++】构造函数,析构函数,拷贝构造,运算符重载,const 成员

【C++】构造函数,析构函数,拷贝构造,运算符重载,const 成员

目录

  • 构造函数
  • 析构函数
  • 拷贝构造函数
    • 关于函数传参
    • 关于默认生成的拷贝构造函数
      • 什么情况下需要显示拷贝构造?
  • 运算符重载
    • 赋值运算符重载
    • 其他运算符重载
  • const 成员

默认成员函数:如果不显示,编译器默认生成

构造函数

构造函数:是一个特殊的成员函数,函数名与类名相同,专门用于初始化类对象

  • 函数名与类名相同
  • 无返回值,没有被声明为void类型
  • 对象实例化时编译器自动调用Date d1,或 Date d2(2023, 4, 21)
  • 构造函数可以重载,一个类中可以有多个构造函数用于多种初始化方式,其中无参数的构造函数为默认构造函数
  • 构造函数:无参数构造函数,全缺省构造,半缺省构造,编译器自动成(无参数和全缺省只能存在一个,否则调用时会产生歧义)
  • 若不主动显示,编译器将会自动生成默认构造函数
     

关于编译器默认生成的构造函数

  • 内置类型的成员不做处理
  • 自定义类型成员,会去调用该自定义类型成员的无参数默认构造函数

对于成员有自定义类型成员的类,不主动显示(定义)构造函数时,编译器会自动生成默认构造函数,在对象实例化时,该自动生成的默认构造函数会去调用该自定义类型成员的默认构造函数,从而完成对象的初始化。
即这种情况下,编译器自动生成的默认构造函数的作用是调用,而不是直接产生效果

  • 建议对内置类型成员设置缺省值

析构函数

对象在销毁时自动调用析构函数,完成的是对象中资源清理工作

  • 构造函数名:~classname
  • 无返回值类型
  • 一个类中只能有一个析构函数
  • 析构函数不能重载
  • 对象生命周期结束,编译器自动调用析构函数

编译器自动生成的析构函数规则同构造函数类似

拷贝构造函数

Date d2(d1);
Date d3 = d1;

  • 拷贝构造函数是构造函数的一个重载
  • 参数只有一个且必须为类类型对象的引用
  • 参数最好用const修饰,以保护引用的原对象数据,同时避免权限放大
  • 若未显示,编译器会自动生成默认的拷贝构造函数,该拷贝构造默认按字节完成拷贝,即浅拷贝或值拷贝
  • 拷贝构造作用场景:
    • 使用已有类型对象创建新对象
    • 函数参数为类类型对象传值传参
    • 函数返回值以类类型对象的值返回
       

关于函数传参

void func(Date d)
{}

Date d1;
func(d1);

  • 调用func函数时需要传参,这里为传值传参,要为d1创建一份临时拷贝,拷贝d1要调用拷贝构造来生成这份临时拷贝
  • 对于自定义类型,必须调用拷贝构造完成,编译器只能对内置类型进行拷贝
  • 此外,函数返回对象时也会调用拷贝构造,(返回引用时不会拷贝构造

关于默认生成的拷贝构造函数

  • 默认生成的拷贝构造函数完成的时浅拷贝,对于内置类型会产生作用

  • 当成员变量中有指向堆空间的指针时,默认拷贝构造的浅拷贝只会拷贝这个指针,结果是拷贝了一个指针指向了同一块空间,但空间没有发生拷贝,就会导致一些麻烦

  • 若对空间中的数据进行操作,会相互影响

  • 析构时,拷贝的对象和原对象两次析构,会对同一块空间析构两次,会报错

  • 为避免上述情况,主动显示拷贝构造以实现深拷贝
     

什么情况下需要显示拷贝构造?

自己实现的析构函数中会释放空间,涉及资源管理时,需要主动实现拷贝构造

 

运算符重载

运算符重载的意义:使运算符能按照自定义的方式作用于自定义类型

赋值运算符重载

  • 赋值运算符重载必须是成员函数
  • 对于内置类型,无须显示实现,编译器生成的默认赋值重载能通过浅拷贝完成任务
  • 对于自定义类型,若涉及资源管理,则必须实现赋值运算符重载
     
  • 赋值重载是针对于两个已经实例化的对象
  • 为支持连续赋值,定义时需设置返回值以作为左值参与到连续赋值
  • 支持连续赋值的运算符都需要设置返回值

 

其他运算符重载

  • 区分与函数重载,使用operator定义
  • 重载参数按照操作数的顺序定义
  • 使用重载的运算符时注意优先级
  • 可以定义在全局,但建议直接声明在类中

 

  • operator不能连接操作符以外的符号
  • 重载操作符必须有一个类类型参数
  • 用于内置类型的运算符含义不能改变
  • 作为类成员函数重载时,注意考虑第一个隐含的this参数

 

const 成员

使用 const 修饰类成员函数以避免权限放大问题
void Func() const; const 修饰的是隐含参数this,以保护自身对象

  • 内部不改变成员变量的成员函数要加上 const
  • 类中可以同时有普通成员函数和const成员函数
int& operator[](int i);//可读可写
const int& operator[](int i) const;//只可读

此外,取地址操作符重载是默认成员函数,一般不用自己定义