• C++中构造函数的手动和自动调用方式


    1,对象的构造通过构造函数来完成,和类名相同且没有返回值,这个时候只有参   数一个特性,构造函数可以自定义参数,这个参数一般而言就是对类进行初始  化来使用的;带有参数的构造函数的意义在于可以使得每个对象有不同的初始   化状态(生活中每个事物必然包含自己的初始化状态,不如人的出生,面向对   象用来将生活中的事物映射的程序设计领域,所以现实世界的情况都必须可以  用面向对象的语言来描述,因此带有参数的构造函数就是非常必要的);

     

     2,带有参数的构造函数:

        1,构造函数可以根据需要定义参数;

        2,一个类中可以存在多个重载的构造函数;

        3,构造函数的重载遵循 C++ 重载的规则;

        4,代码示例:

    1 class Test
    2 {
    3 public:
    4     Test(int v)
    5     {
    6         // use v to initialize member
    7     }
    8 };

       

     3,对象定义和对象声明的区别:

        1,对象定义:申请对象的空间并调用构造函数;

           1,第一步,必须申请对象所占用的内存空间;

           2,第二步,调用构造函数;

        2,对象声明:告诉编译器存在这样一个对象;

           1,对象在哪里定义的不知道,链接的时候回去找;

           2,预处理,编译器对源代码进行检查并生成目标文件,链接器在各个目标文件中寻找目标文件存在的一些名字;

           3,对象声明时,没有对象定义时的两个步骤;

        3,代码示例:

    1 Test t;  // 定义对象并调用构造函数;
    2 
    3 Int main()
    4 {
    5     // 告诉编译器存在名为 t 的Test对象;
    6     extern Test t;
    7 
    8     return 0;
    9 }

        4,对象的声明中可以在构造函数参数中给出默认值,对象的定义中不能够在构 造函数参数中给出默认值;

       

     4,构造函数的自动调用(第一种初始化对象方式):

     1 #include <stdio.h>
     2 
     3 class Test
     4 {
     5 public:
     6     Test() 
     7     { 
     8         printf("Test()
    ");
     9     }
    10     
    11     Test(int v) 
    12     { 
    13         printf("Test(int v), v = %d
    ", v);
    14     }
    15 };
    16 
    17 int main()
    18 {
    19     Test t;      // 调用 Test()
    20     Test t1(1);  // 初始胡第一种方式的参数式自动调用,调用 Test(int v);这里也是定义对象,看上去非常像函数调用,但是这里是告诉编译器要调用带有参数的函数,由重载规则确定调用的是那个构造函数;
    21     Test t2 = 2; // 初始化第一种方式的赋值式自动调用,调用 Test(int v);C 语言中初始化的方法,定义一个变量后,立即指明一个值,通过赋值符号指明;这在面向对象中其实也是对象的定义,并且指明想用右值初始化左值;
    22  
    23     t = t2;  // 这是赋值操作,这里运行后不会调用构造函数,没有打印语句;初始化会调用构造函数,赋值则看后续课程;
    24  
    25     int i = 1;  // 用 1 对 i 进行初始化;
    26     i = 1;  // 用 1 对 i 进行赋值;赋值和初始化是不同的;在面向对象当中,不同在于初始化是要调用构造函数的;
    27        
    28     int i(100);  // 初始化的第二种写法,同 int i = 100;; 
    29     
    30     printf("i = %d
    ", i);
    31     
    32     return 0;
    33 }

        1,实验结果说明:

           1,初始化和赋值看上去相同之处在于当初始化用赋值符号表达的时候;

           2,不同之处在于初始化要调用构造函数,而赋值不会;

       

     5,构造函数的调用:

        1,一般情况下,构造函数在对象定义时被自动调用;

        2,一些特殊情况下,需要手工调用构造函数:

           1,如何创建对象数组;

       

     6,构造函数的手工调用(第二种初始化对象方式)编程实验:

     1 #include <stdio.h>
     2 
     3 class Test
     4 {
     5 private:
     6     int m_value;
     7 public:
     8     Test() 
     9     { 
    10         printf("Test()
    ");
    11         
    12         m_value = 0;
    13     }
    14     Test(int v) 
    15     { 
    16         printf("Test(int v), v = %d
    ", v);
    17         
    18         m_value = v;
    19     }
    20     int getValue()
    21     {
    22         return m_value;
    23     }
    24 };
    25 
    26 int main()
    27 {
    28     Test ta[3];  // 按照 C 语言的方法定义 3 个 Test 对象的数组 ta;结果调用了 3 个 Test() 函数;
    29     
    30     for(int i=0; i<3; i++)  // 循环结果打印出 3 个 0,这不一定是我们想要的;编译器默认的调用了 Test();
    31     {
    32         printf("ta[%d].getValue() = %d
    ", i , ta[i].getValue());
    33     }
    34     
    35     Test ta[3] = {Test(), Test(1), Test(2)};  // 手动调用构造函数;
    36     
    37     for(int i=0; i<3; i++)  // 循环结果为 0 1 2;分别调用了相应的构造函数;
    38     {
    39         printf("ta[%d].getValue() = %d
    ", i , ta[i].getValue());
    40     }
    41     
    42     Test t = Test(100);  // 初始化第二种方式,手工调用构造函数;
    43     
    44     printf("t.getValue() = %d
    ", t.getValue());
    45     
    46     return 0;
    47 }

       

     7,小实例:

        1,需求:开发一个数组类解决原生数组的安全性问题:

           1,提供函数获取数组长度;

               1,C++ 要兼容 C 语言中的数组,但是 C 语言中的数组没有长度信息,用着用着就越界了;

           2,提供函数获取数组元素;

           3,提供函数设置数组元素;

          

     8,数组类的实现编程实验:

        1,IntArray.h 文件:

     1 #ifndef _INTARRAY_H_
     2 #define _INTARRAY_H_
     3 
     4 class IntArray
     5 {
     6 private:
     7     int m_length;
     8     int* m_pointer;
     9 public:
    10     IntArray(int len);
    11     int length();
    12     bool get(int index, int& value);  // 用 bool 类型作为返回值是为了安全性,安全性的体现见数组类的实现;
    13     bool set(int index ,int value);
    14     void free();  // 用来释放 m_pointer 指向的堆空间
    15 };
    16 
    17 #endif

        2,IntArray.cpp 文件:

     1 #include "IntArray.h"
     2 
     3 IntArray::IntArray(int len)  // 不加作用域分辨符时,是全局函数(此时仅名字前缀相同而已),所以要加作用域分辨符指明是数组类中的函数;
     4 {
     5     m_pointer = new int[len];  // new int(len) 指的是设置初始值;
     6     
     7     for(int i=0; i<len; i++)
     8     {
     9         m_pointer[i] = 0;
    10     }
    11     
    12     m_length = len;
    13 }
    14 
    15 int IntArray::length()
    16 {
    17     return m_length;
    18 }
    19 
    20 bool IntArray::get(int index, int& value)
    21 {
    22     bool ret = (0 <= index) && (index < length());  // 进行安全性检查,是安全性的体现;
    23     
    24     if( ret )
    25     {
    26         value = m_pointer[index];  // 通过引用返回一个值;
    27     }
    28     
    29     return ret;  // 越界则返回 false;
    30 }
    31 
    32 bool IntArray::set(int index, int value)
    33 {
    34     bool ret = (0 <= index) && (index < length());
    35     
    36     if( ret )
    37     {
    38         m_pointer[index] = value;
    39     }
    40     
    41     return ret;
    42 }
    43 
    44 void IntArray::free()
    45 {
    46     delete[]m_pointer;
    47 }

        3,IntArray 的使用:

     1 #include <stdio.h>
     2 #include "IntArray.h"
     3 
     4 int main()
     5 {
     6     IntArray a(5);    
     7     
     8     for(int i=0; i<a.length(); i++)
     9     {
    10         a.set(i, i + 1);
    11     }
    12     
    13     for(int i=0; i<a.length(); i++)
    14     {
    15         int value = 0;
    16         
    17         if( a.get(i, value) )
    18         {
    19             printf("a[%d] = %d
    ", i, value);
    20         }
    21     }
    22     
    23     a.free();
    24     
    25     return 0;
    26 }

        4,这里展示了面向对象的强大,我们可以通过类来封装一些之前学习到的概念,并且可以将这些概念上的缺陷通过封装来弥补开来;

       

     9,小结:

        1,构造函数可以根据需要定义参数;

        2,构造函数之间可以存在重载关系;

        3,构造函数遵循 C++ 中重载函数的规则;

        4,对象定义时会触发构造函数的调用;

           1,构造函数调用方式分为自动调用和手工调用两种;

           2,自动调用的形式又分为参数式和赋值式;

           3,即初始化时,分为两种调用方式三种书写形式;

        5,在一些情况下可以手动调用构造函数;

  • 相关阅读:
    OS模块
    利用一个random模块生成一个随机验证码功能
    random模块
    模块2
    模块module
    Java笔记汇总
    学习路上——技术书籍摸爬滚打
    web前端知识汇总——持续更新
    Python之路——进入Python学习
    Python细节备忘——时常拾遗以及关键点
  • 原文地址:https://www.cnblogs.com/dishengAndziyu/p/10904899.html
Copyright © 2020-2023  润新知