• c++构造函数(初始化式)被忽略的东西


    不管是在c++,还是c#,或是java中,当人们一提到构造函数是,马上就回有人回答,是用来初始化成员变量的,没错,但是殊不知,后面却隐含了很多东西。

    首先:构造函数用初始化式与在函数里面直接初始化有什么不同。

    我先简单说一下初始化式,可能有人已经忘了什么是构造函数的初始化式。其实初始化式就是一个以冒号开始,接着是一个以逗号分隔的数据成员列表,每个数据成员后面跟着一个放在圆括号里的初始化式。而初始化式只能在构造函数的定义中而不能再声明中指定。如:

    class A{
      public int a,b;
     public string c;
      A(const string &s):a(3),b(4),c(s){ }
    };
    

      

    我们也可以由下面的方式进行成员变量的初始化:

    class A{
      public int a,b;
      public string c;
      A(const string &s){ a = 3;b = 4;c = s}
    };
    

      


    那么上面两个有什么区别呢?
    我们先说一下,构造函数的执行过程分为两个阶段:(1)初始化阶段;(2)普通计算阶段。
    普通计算阶段是由构造函数的函数体内的语句来构成。
    那么我们来分析一下第二种方式的初始化:
    这个构造函数在给类A的成员变量赋值之前,第一步要进行初始化变量c。所以这个构造函数使用了内部隐式的string类的构造函数对c进行初始化。当我们执行到普通计算阶段时,又对c进行了赋值。
    那么什么样的构造函数必须使用初始化式来对成员变量进行赋值呢?
    我这里给出两种,一种是const,另一种是引用类型。
    为什么呢?我们可以想一想const变量要求在声明的时候就进行初始化,而如果我们采用第二种方式的话,在构造函数的第二个阶段,又会对const变量赋一次值,而这又违反了const变量的性质。关于引用类型的探讨留给读者。


    第二个问题:
    初始化列表中的次序
    我们一般可能会认为初始化列表的顺序就是初始化成员函数的顺序,其实不是这样。而应该是定义成员变量的顺序。

    下面给一个例子:

    class M{
    int i;
    int j;
    public:
    M(int val):j(val),i(j){}

    };


    这个例子看起来似乎是用val初始化j,然后用j再初始化i。
    然而,i其实是被先初始化的,他用未被初始化的j来初始化。
    第三个问题
    先看下面的程序

    class M{
    public: string a;
    M():a(10,'a'){}

    };
    void main()
    {
    char* c = new char[10];
    M m;

    strcpy(c,m.a.c_str());
    cout<<c;
    }



    这个程序中输出了九个a
    其实在初始化式中,如果有其他类类型的变量,可以直接使用那个类的构造函数来对这个M类中的对象初始化。例子中就是用string类的构造函数来初始化的。
    至于为什么用c_str()函数,可以看下面这篇文章。
    http://blog.csdn.net/gaotengguojianhong/article/details/7037942

    
    
    
    
    
    
  • 相关阅读:
    Lua 脚本限制访问频率过高的IP
    h2:无法自动建库解决(H2 Database Engine)
    在保留所有列的pandas中获取每个类别的前n个值...
    python中使用多进程multiprocessing并获取子进程的返回值
    openresty nginx http状态码
    python process返回值_在多处理Python中从multiprocessing.Queue()返回值
    修改nginx的http响应头server字段
    mysql 保留两位小数
    Nginx location模块整理
    Python量化分析,计算KDJ (使用如下方法计算与国内财经软件显示一致)
  • 原文地址:https://www.cnblogs.com/gaoteng/p/2350367.html
Copyright © 2020-2023  润新知