一、类的构造函数

什么是构造函数

和类具有相同名称,并且没有返回值类型的函数,就是类的构造函数

概念模糊、直接举例:

1

2

3

4

5

6

7

8

9

10

11

12

#include <stdio.h>

#include <windows.h>

struct Test

{

    Test()        // 和类具有相同的名、并且没有返回值

    {

    }

};

int main()

{

    return 0;

}

构造函数的特点

直接先来说特点吧,然后论证:

1、构造函数在定义对象的时候被调用

2、构造函数可以进行函数重载,可以有很多个

3、创建对象时默认调用的是无参构造

证明1:

构造函数在定义对象的时候被调用;

论证如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

#include <stdio.h>

struct Test

{

    Test()

    {

        printf("你调用了构造函数\n");       // 此处下断点、如果该函数被调用肯定会停下来。

    }

};

int main()

{

    Test te;

    printf("接力\n");

    return 0;

}

我们在Test()构造的输出语句上加断点、当程序调用Test的printf肯定会停下来,这个时候我们转到反汇编,单步步过、直到函数返回之后,就能知到刚刚是在哪里调用的构造函数了

vs2010:F7编译、F5调试、ALT+8反汇编:

F10一直运行到返回:

这里编译器做了优化,可以直接看出来是在Test定义对象的时候调用了构造。

证明2:

构造函数可以进行函数重载,可以有很多个;

论证如下:

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

#include <stdio.h>

#include <Windows.h>

struct Test

{

    Test()

    {

        printf("你调用了构造函数\n");       // 此处下断点、如果该函数被调用肯定会停下来。

    }

    Test(int a)

    {

        printf("重载%d\n",a);

    }

    Test(int a, int b)

    {

        printf("重载%d\n",a+b);

    }

};

int main()

{

    Test te;

    Test te1(1);

    Test te2(1,1);          // 注意、调用有参的构造函数时,需要传递参数

    system("pause");

    return 0;

}

重载了两个,注意:调用有参数的构造时,需要传递参数。

运行可以通过:

证明3:

创建对象时默认调用的是无参构造;

论证如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

#include <stdio.h>

#include <Windows.h>

struct Test

{

    Test(int a)

    {

        printf("重载%d\n",a);

    }

    Test(int a, int b)

    {

        printf("重载%d\n",a+b);

    }

};

int main()

{

    Test te;            // 普通定义对象的方式、不带参数

    system("pause");

    return 0;

}

首先我们删除无参构造,看看能否编译通过:

不可以

然后删除有参构造:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

#include <stdio.h>

#include <Windows.h>

struct Test

{

    Test()

    {

        printf("你调用了构造函数\n");       // 此处下断点、如果该函数被调用肯定会停下来。

    }

};

int main()

{

    Test te;

    system("pause");

    return 0;

}

可以

全部都加上:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

#include <stdio.h>

#include <Windows.h>

struct Test

{

    Test()

    {

        printf("你调用了构造函数\n");       // 此处下断点、如果该函数被调用肯定会停下来。

    }

    Test(int a)

    {

        printf("重载%d\n",a);

    }

    Test(int a, int b)

    {

        printf("重载%d\n",a+b);

    }

};

int main()

{

    Test te;

    system("pause");

    return 0;

}

运行结果:

这已经证明了,Test te;平常这样定义对象的时候,调用的是无参构造。如果需要调用有参构造,必须传入参数;

这个特点很简单、有参函数肯定要传参嘛,所以定义对象的时候肯定要传入参数啊;

但是这里建议无论什么时候写类,最好还是写上无参构造,哪怕什么都不做也尽量写上,避免不必要的麻烦。

构造函数的作用

一般用于初始化类的成员

如下:

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

#include <stdio.h>

#include <Windows.h>

struct Test

{

    int x;

    int y;

    int z;

    Test()

    {

    }

    Test(int x,int y,int z)                     // 构造函数初始化对象

    {

        this->x = x;

        this->y = y;

        this->z = z;

    }

};

int main()

{

    Test te;

    Test te1(1,2,3);                            // 定义对象并调用有参构造进行初始化

    printf("%d %d %d\n",te1.x,te1.y,te1.z);     // 输出看看是否初始化成功

    system("pause");

    return 0;

}

运行如下:

初始化成功。

二、类的析构函数

什么是析构函数

类的构造函数名前加上'~'这个符号,就是类的析构函数

概念模糊、代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

#include <stdio.h>

#include <Windows.h>

struct Test

{

    Test()

    {

        printf("你调用了一次类的构造函数\n");

    }

    ~Test()

    {

        printf("你调用了一次类的析构函数\n");

    }

};

int main()

{

    Test te;

    // system("pause");        // 这里就不要让程序停下来了,不然析构不了

    return 0;

}

~Test(){}就这个样子

析构函数的特点

依然直接先来说特点,然后论证:

1、析构函数不能重载、不能有参数

2、析构函数在变量声明周期结束时被调用

3、析构函数被调用分两种情况:堆栈中定义的对象、全局区中定义的对象


 

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐