• C++构造函数(一)


    本篇是介绍C++的构造函数的第一篇(共二篇),属于读书笔记,对C++进行一个系统的复习。

    构造函数的概念和作用

    全局变量未初始化时为0,局部变量未初始化时的值却是无法预测的。这是因为,全局变量的初始化是再程序装载时便一次性完成的,自动地初始化为零并不会有额外的开销,因此编译器默认初始化为零。但是对局部变量并没有这样的操作,需要程序去完成初始化。

    基本类型变量的初始化只需要在定义时赋值就可以了,但是对于对象的初始化,情况就要复杂一些。比如,有的对象需要在创建时就令某个指针指向一块内存空间,这就涉及到空间的分配;再比如,有的对象包含文件操作,在创建时就需要打开特定文件。举这两个例子是要说明,对象的初始化,不仅仅是简单赋值那么简单。因此构造函数(constructor)是必要的,它的存在就是为了完成对象的初始化工作。

    构造函数名字和类名一样,没有返回值,可以重载。可以有多个构造函数,如果没有就自动生成一个默认的构造函数,但是它什么也不做。

    默认构造函数

    自动生成的构造函数是一个没有参数的构造函数。但凡自己已经写了一个构造函数,都不会自动生成无参的构造函数。不论是程序员自己写的无参构造函数还是自动生成的无参构造函数,只要是无参构造函数,就称为默认构造函数。那么,考虑下面一种情况:程序员只写了有参的构造函数,这种情况下就不存在默认构造函数。所以默认构造函数不一定存在,或者说无参的构造函数不一定存在。为什么要强调无参的构造函数不一定存在,有没有哪种构造函数一定是存在的呢?复制构造函数是一定存在的,在后文介绍。

    对象在生成的时候一定会调用某个构造函数初始化,而对象一旦生成,就再也不会在其上调用构造函数。

    构造函数是负责内存的分配吗?不是的,它只负责初始化。所以创建一个对象的过程是,先内存分配(在堆或栈上),之后在分配好的内存上调用构造函数。

    构造函数在数组中的使用

    像 int a[3] = { 0 ,1 ,2 }; 这样的语句就实现了数组的初始化。如何给一个对象数组初始化呢,可以使用类似的方法。

    1 class CNum {
    2 
    3 int num;
    4 public:
    5 
    6 CNum(){ num = 0;}
    7 CNum(int a){ num = a;}
    8 CNum(int a, int b){ num = a + b;}
    9 }

    可以这样调用:

    1 CNum n1[3];                   //调用了三次无参构造函数,结果是{0,0,0}
    2 CNum n2[3] = {0, 1, 2};           //调用了三次CNum(int a),结果是{0,1,2}
    3 CNum n3[3] = {0, 1};             //调用了两次CNum(int a),和一次无参构造函数,结果是{0,1,0}
    4 CNum n4[3] = {0, CNum(1,2), CNum(2,3)};  //调用了一次无参构造函数和两次CNum(int a, int b),结果是{0,3,5}

    想在堆上生成数组可以这样:

    1 CNum * ptrnum[3] = {new CNum(1,2), new CNum(2,3)};

    这样生成的实际上是一个指针数组,前两个元素指向的对象使用了CNum(int a, int b)初始化,第三个元素没有初始化,是一个野指针(请避免这样做)。所以这一个语句实际上调用了两次构造函数。

     

  • 相关阅读:
    sequence——强行推式子+组合意义
    2018-2-25-git-rebase-合并多个提交
    2018-2-25-git-rebase-合并多个提交
    2019-9-2-给博客添加rss订阅
    2019-9-2-给博客添加rss订阅
    2019-10-31-Resharper-去掉注释拼写
    2019-10-31-Resharper-去掉注释拼写
    2018-8-10-win10-sdk-是否向下兼容
    2018-8-10-win10-sdk-是否向下兼容
    2019-8-15-win10-edge-打开闪退问题
  • 原文地址:https://www.cnblogs.com/painterQ/p/7003814.html
Copyright © 2020-2023  润新知