广告位联系
返回顶部
分享到

C++中类的六大默认成员函数的介绍

C语言 来源:互联网 作者:佚名 发布时间:2022-10-16 21:18:11 人浏览
摘要

一、类的默认成员函数 二、构造函数Date(形参列表) 构造函数主要完成初始化对象,相当于C语言阶段写的Init函数。 默认构造函数:无参的构造函数或全缺省的构造函数,二者只能存在

一、类的默认成员函数

二、构造函数Date(形参列表)

构造函数主要完成初始化对象,相当于C语言阶段写的Init函数。

默认构造函数:无参的构造函数或全缺省的构造函数,二者只能存在一个,同时存在类中,调用时会出现二义性。

1、构造函数的函数名和返回值

构造函数的函数名和类名相同且无返回值

2、构造函数的调用

对象实例化时,编译器自动调用对应的构造函数且只调用一次

3、构造函数的重载

构造函数可以重载(多种初始化方式)注意:虽然全缺省和无参的构造函数构成重载,但是调用时存在二义性。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

class Date

{

public:

    //构造函数的重载

    Date()

    {

  

    }

    Date(int year,int month,int day)

    {

        _year = year;

        _month = month;

        _day = day;

    }

private:

    int _year;

    int _month;

    int _day;

};

int main()

{

    Date d1;//创建并通过无参构造函数初始化对象时,无需加括号,不然变成了函数声明

    Date d2(2022,9,23);

    return 0;

}

4、系统生成的默认构造函数

如果我们在类中不写构造函数,C++编译器会在类中帮我们生成一个无参的构造函数。我们写了构造函数,那么系统将不会生成。

我们构造对象并调用构造函数时,初始化的数据是随机值:

5、系统生成的默认构造函数的作用

系统生成默认构造函数对内置类型不处理,对自定义类型调用他的构造函数。

注意:下方代码中,Date类中的内置类型将会调用Date类中的构造函数;Date类中的Time _t将会调用Time类中的构造函数。

6、可以在内置类型的成员变量的声明中给缺省值

C++11中针对内置类型不处理初始化为随机值的问题,打了补丁:内置类型成员变量在类中声明可以给默认值,甚至可以给动态开辟的缺省值,缺点是不能判断空间是否开辟成功。

注意这里的默认值是缺省值,不是初始化。初始化是要等对象调用时才叫初始化。

1

2

3

4

5

6

7

8

class Date

{

private:

    int _year=1;

    int _month=2;

    int _day=3;

    int* arr = (int*)malloc(sizeof(int) * 5);

};

这个特性只能用于解决默认构造函数初始化为随机值的问题。这个特性不能解决对象的多种初始化方式(这也是构造函数支持重载的原因),构造函数该写还是得自己写。

7、初始化列表初始化

  • 1、对象的每个成员变量是在初始化列表部分进行初始化,而函数体内的行为是对成员函数赋初值。
  • 2、如果没有在初始化列表里显示初始化某个成员函数,对于内置类型,有缺省值用缺省值,无缺省值初始化为随机值;对于自定义类型将会调用它的默认构造函数,没有找到默认构造就会报错。
  • 3、引用、const、无默认构造函数的自定义类型必须通过初始化列表初始化。
  • 4、成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关。

1

2

3

4

5

Date(int year=1,int month=1,int day=1)//缺省值

    :_year(year)//成员变量的定义

    ,_month(month)

    ,_day(day)

{}//成员变量的赋初值

总结:尽量使用使用初始化列表进行初始化,在类中尽量提供默认构造函数(最好是全缺省的默认构造函数)

8、单参数构造(C++98)、多参数构造(C++11)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

class Date

{

public:

    Date(int year=1,int month=1,int day=1)

        :_year(year)

        ,_month(month)

        ,_day(day)

    {}

private:

    int _year;

    int _month;

    int _day;

};

int main()

{

    //单参数的构造,构造+拷贝,编译器直接优化为构造C++98

    Date d1 = 2022;

    //临时对象具有常性,构造+拷贝,编译器不会优化

    const Date& d2 = 2023;

    //多参数的构造C++11

    Date d3 = { 2022,10,16 };

    return 0;

}

  • 1、在构造时,支持等号加参数的构造形式,实际上发生的是隐式类型转换。2022由int类型隐式类型转换为Date型的临时对象,该临时对象再将它的值拷贝构造给d1。
  • 2、2023会隐式类型转换为Date类型的临时对象,具有常属性。d2是这个临时对象的引用,所以需要加上const。这里发生构造+拷贝构造,涉及临时对象的引用,所以编译器并不会发生优化。
  • 3、可以使用explicit关键字修饰构造函数,会禁止隐式类型转换。

三、析构函数~Date()

析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。资源包括动态开辟的空间,文件的关闭等。相当于C语言阶段写的destroy函数。

1、析构函数的函数名、参数和返回值

析构函数的函数名是类名前加~,无参无返回值类型。

2、析构函数的特点

一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载

对象生命周期结束时,C++编译系统系统自动调用析构函数

3、编译器生成的默认析构函数

对于编译器生成的默认析构函数,对自定义类型调用他的析构函数。对于内置类型,没有需要处理资源。

注意:Date类中的内置类型会调用Date类中的析构函数;Date类中的自定义类型Time _t会调用Time的析构函数。

四、拷贝构造Date(const Date& d)

1、拷贝构造函数是构造函数的重载

拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。

拷贝构造函数的函数名和构造函数相同,无返回值,在参数上和构造函数构成重载。

2、拷贝构造函数的参数

拷贝构造函数的参数只有一个并且是类类型对象的引用。如果使用传值传参的方式进行拷贝构造,在传值的过程中实参需要拷贝一份数据给形参,这个过程需要调用拷贝构造。形成层层传值引发对象的拷贝的递归(有递无归)调用。

3、若未显式定义,编译器会生成默认的拷贝构造函数

默认的构造函数对于内置类型按照字节拷贝。对于自定义类型则调用它的拷贝构造函数。

4、拷贝构造函数的深浅拷贝

通过默认的拷贝构造函数构造的对象,按字节完成拷贝。这种拷贝被称为浅拷贝(值拷贝)。

1

2

3

4

5

6

int main()

{

    Date d1(2022,9,24);

    Date d2(d1);

    return 0;

}

对于内置类型,使用浅拷贝即可,系统默认生成的就可以做到,所以我们不用动手写拷贝构造函数。注意这里有d1,d2两个对象,当main函数生命周期结束时,这两个对象均会发生一次析构,d2先析构,d1后析构。(后定义的先销毁,类似栈的后进先出原则)

但是浅拷贝对于占用“资源”的成员变量时(例如成员变量中有动态开辟或fopen的资源),指针虽然复制了,但是所指向的内容却没有复制,析构时存在同一块空间被释放两次的问题。需要进行深拷贝。深拷贝的拷贝构造函数必须自己手动实现。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

class Stack

{

public:

    Stack(int capacity=100)//构造函数

    {

        _capacity = capacity;

        _top = 0;

        _arr = (int*)malloc(sizeof(int) * 5);

        if (_arr == nullptr)

        {

            perror("malloc fail");

            exit(-1);

        }

    }

    //Stack(const Stack& st)//浅拷贝,栈这个类不能用浅拷贝

    //{

    //  _capacity = st._capacity;

    //  _top = st._top;

    //  _arr = st._arr;

    //}

    Stack(const Stack& st)//深拷贝

    {

        _capacity = st._capacity;

        _top = st._top;

        _arr = (int*)malloc(sizeof(int) * st._top);

        if (_arr == nullptr)

        {

            perror("malloc fail");

            exit(-1);

        }

        memcpy(_arr, st._arr,sizeof(int)*st._top);

    }

    ~Stack()//析构函数

    {

        _capacity = 0;

        _top = 0;

        free(_arr);

        _arr = nullptr;

    }

private:

    int* _arr;

    int _top;

    int _capacity;

};

栈这个类因为成员变量中有动态开辟的空间,所以要用深拷贝。

5、拷贝构造函数调用场景

  • 1、使用已存在的对象创建新对象
  • 2、函数参数类型为类的类型对象(传值调用,实参拷贝给形参)
  • 3、函数返回值类型为类的良心对象(传值返回)

五、赋值运算符重载Date& operator=(const Date& d )

1、赋值运算符重载

只有赋值运算符是默认成员函数。

2、赋值运算符重载的注意事项

  • 1、参数是const T&,传引用可以减少一次拷贝构造。
  • 2、返回值是*this的引用,引用返回,减少一次拷贝构造,有返回值是为了支持函数的链式访问。
  • 3、务必检查下是否支持自己给自己赋值。
  • 4、赋值运算符重载必须是类中的默认成员函数,不能写在全局。
  • 5、系统默认生成的赋值运算符重载会完成值拷贝。

六、取地址操作符重载和const取地址操作符重载

1

2

3

4

5

6

7

8

9

10

Date* operator&()

{

    return this;

    //return nullptr;

}

const Date* operator&()const

{

    return this;

    //return nullptr;

}

不用自己写,除非想让别人通过取地址操作符获取到特定值(自己在重载函数内部写)或屏蔽类地址 


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://blog.csdn.net/gfdxx/article/details/127313617
相关文章
  • C++时间函数整理介绍
    一、 时间概念 格林威治时间GMT(Greenwich Mean Time) 格林威治皇家天文台为了海上霸权的扩张计划,在十七世纪就开始进行天体观测。为了天
  • C++中类的六大默认成员函数的介绍

    C++中类的六大默认成员函数的介绍
    一、类的默认成员函数 二、构造函数Date(形参列表) 构造函数主要完成初始化对象,相当于C语言阶段写的Init函数。 默认构造函数:无参的构
  • C/C++实现遍历文件夹最全方法总结介绍

    C/C++实现遍历文件夹最全方法总结介绍
    一、filesystem(推荐) 在c++17中,引入了文件系统,使用起来非常方便 在VS中,可以直接在项目属性中调整: 只要是C++17即以上都可 然后头文件
  • C语言实现手写Map(数组+链表+红黑树)的代码

    C语言实现手写Map(数组+链表+红黑树)的代码
    要求 需要准备数组集合(List) 数据结构 需要准备单向链表(Linked) 数据结构 需要准备红黑树(Rbtree)数据结构 需要准备红黑树和链表适配策略
  • MySQL系列教程之使用C语言来连接数据库

    MySQL系列教程之使用C语言来连接数据库
    写在前面 知道了 Java中使用 JDBC编程 来连接数据库了,但是使用 C语言 来连接数据库却总是连接不上去~ 立即安排一波使用 C语言连接 MySQL数
  • 基于C语言实现简单学生成绩管理系统

    基于C语言实现简单学生成绩管理系统
    一、系统主要功能 1、密码登录 2、输入数据 3、查询成绩 4、修改成绩 5、输出所有学生成绩 6、退出系统 二、代码实现 1 2 3 4 5 6 7 8 9 10 11
  • C语言实现共享单车管理系统

    C语言实现共享单车管理系统
    1.功能模块图; 2.各个模块详细的功能描述。 1.登陆:登陆分为用户登陆,管理员登陆以及维修员登录,登陆后不同的用户所执行的操作
  • C++继承与菱形继承的介绍

    C++继承与菱形继承的介绍
    继承的概念和定义 继承机制是面向对象程序设计的一种实现代码复用的重要手段,它允许程序员在保持原有类特性的基础上进行拓展,增加
  • C/C++指针介绍与使用介绍

    C/C++指针介绍与使用介绍
    什么是指针 C/C++语言拥有在程序运行时获得变量的地址和操作地址的能力,这种用来操作地址的特殊类型变量被称作指针。 翻译翻译什么
  • C++进程的创建和进程ID标识介绍
    进程的ID 进程的ID,可称为PID。它是进程的唯一标识,类似于我们的身份证号是唯一标识,因为名字可能会和其他人相同,生日可能会与其他
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计