由C++构造函数初始值列表想到的

来源:互联网 发布:js.users.51.la是什么 编辑:程序博客网 时间:2024/05/23 00:07

引子

大家在编写C++代码的时候,总是会遇到下面这个问题,什么时候为构造函数提供初始值列表(当然,推荐做法都是以初始值列表代替构造函数体内赋值)。数据成员初始化动作是在构造函数体之前的,相对应的,析构函数的数据成员销毁动作是在析构函数体之后的。所常见的必须提供初始值列表的情况有,

  • 数据成员含有const成员变量
  • 数据成员含有引用

前面两个比较好理解,const和引用都是必须在声明时赋初值的。但是数据成员中有自定义类型时,就要考虑自定义类型有没有默认构造函数了,例如下面代码:

class B{public:    int mem;    B(int para) : mem(para) {}};class A{public:    B mem_b;    A(int para)     {         // 注意这种赋值有一个隐式操作        // mem_b = static_cast<B>(mem);        // 或        // mem_b = temp(mem);        // 然后再调用拷贝赋值运算符赋值给mem_b        mem_b = mem;     }};

上述代码编译是不会通过的,因为数据成员mem_b没有提供默认构造函数,所以在进入函数体赋值之前,是要报错的。注意,如果自定义类型没有提供拷贝赋值运算符,编译器会为其提供合成的拷贝赋值运算符执行简单内存拷贝操作。

但是为什么人们经常会忽视第三种情况呢,这是由于人们有个误区。

下意识将内置类型和自定义类型分开

其实自定义类型和内置类型说到底都是类型,都是描述数据在内存中的组织方式和对应的操作。这样说是不严谨的,编译原理中对数据类型的定义是,一组值得集合,以及对这组值进行的操作(运算)的集合。数据在计算机内存中无非是二进制位串的集合,本身没有任何意义,有意义的是如何对其进行解释。

任何语言都有自定义类型,如果语言只有内置类型那么语言的易用性就会有很大折扣。自定义类型是由自定义类型和或者是内置类型的集合构成的,是由现有类型的笛卡尔积表示的。但是自定义类型是有前提的,就是不能存在递归情况,如下所示,

class A{public:    int mem;    A mem_a;};

这种情况下,编译器对类型A的推导是不会终止的。所以C++规定自定义类型时,需要数据成员是完整类型。

自定义类型与内置类型没什么区别,都是一组值的集合和在这些值上的操作。只是这种类型的值域,以及其上的操作需要用户自己来控制,所以有许多情况需要用户注意。相对应的,类模版是构造自定义类型的模板,让用户在编写代码时能够动态定义用户类型。

0 0
原创粉丝点击