请注意以下继承体系中各class的constructors写法:

 1 class CPoint
2 {
3 public:
4 CPoint(float x=0.0)
5 :_x(x){}
6
7 float x() {return _x;}
8 void x(float xval){_x=xval;}
9 protected:
10 float _x;
11 };
12
13 class CPoint2d:public CPoint{
14
15 public:
16 CPoint2d(float x=0.0,float y=0.0)
17 :CPoint(x),_y(y){}
18
19 float y(){return _y;}
20 void y(float yval){_y=yval;}
21 protected:
22 float _y;
23 };
24
25 class CPoint3d:public CPoint2d{
26 public:
27 CPoint3d(float x=0.0,float y=0.0,float z=0.0)
28 :CPoint2d(x,y),_z(z){}
29
30 float z(){return _z;}
31 void z(float zval){_z=zval;}
32
33 protected:
34 float _z;
35
36
37 };

  在constructor声明之后有一个:符号,后面紧跟着一个(以上)的函数调用动作,这一行就是所谓的initialization list。它的作用是在进入constructor主体动作之前,,先唤起其中所列的函数。例如上面的:

  第5行表示:在执行CPoint::CPoint(x)之前,先执行_x(x); (注:语言内建类型如int、float、long等等也是一种class,因为变量_x的类型是float,所以_x(x)的意思是启动“float class”的constrnctor,也就把_x的初值设为x;

  第17行表示:执行CPoint2d::CPoint2d(x,y)之前,先执行CPoint(x)和_y(y).

  第28行表示:执行CPoint3d::CPoint3d(x,y,z)之前,先执行CPoint2d(x,y)和_z(z).

  因此当我产生一个CPoint3d object如下:

CPoint3d aPoint3d(1.1, 2.2, 3.3);

  会有以下六个动作依序被调用:

_x(1.1); // 相当于 _x = 1.1;
CPoint::CPoint(1.1); // 本例沒做什么事
_y(2.2); // 相当于 _y = 2.2;
CPoint2d::CPoint2d(1.1, 2.2); // 本例沒做什么事
_z(3.3); // 相当于_z = 3.3;
CPoint3d::CPoint3d(1.1, 2.2, 3.3); // 本例沒做什么事

  你可能会问,既然继承体系中的建构方式是由内而外,由上而下,那么这里产生个CPoint3d object,必然会调用CPoint2d和CPoint的constrnctor,而所有初始化动作都可以在其中完成,initialization list的出现会不会是显得多此一举?做个测试就知道了,把上一段27行的代码改为这样试试:

CPoint3d( float x = 0.0, float y = 0.0, float z = 0.0 ) { _z = z; }

  其中没有指定initialzation list。结果竟然无法通过编译:

error C2668: 'CPoint2d::CPoint2d' : ambiguous call to overloaded
function

  也就是说,当编译器根据继承体系往上一层调用base class constructor时,发现CPoint2d有两个constructors,而它不知道应该调用哪一个。这就是initialization list最明显的存在的价值。如果本例的CPoint2d只有一个constructor,像这样:

1 class CPoint2d : public CPoint {
2 public:
3   CPoint2d( ) { _y = 0.0; } // default constructor
4 protected:
5   float _y;
6 };

  或者这样

1 class CPoint2d : public CPoint {
2 public:
3 CPoint2d( float x = 0.0, float y = 0.0 )
4 : CPoint( x ), _y( y ) { }
5 protected:
6 float _y;
7 };

  而 CPoint3d constructor 中沒有列出 initialization list,像这样:

1 class CPoint3d : public CPoint2d {
2 public:
3 CPoint3d( float x = 0.0, float y = 0.0, float z = 0.0 ) { _z = z; }
4 protected:
5 float _z;
6 };

  那么并不会出现前面的编译错误。

  以上的讨论是针对base class的建构,同理对于member class 也是一样。如果member calss有一个以上的constructors,那么内含embedded object的那个class就必须在其constructor中指定initialization list,否则一样会出现编译错误。

  initialization list到底会在编译器底层发生什么影响呢?编译器会以“适当的次序”将initialization list中指定的member调用动作安插到constructor之内,并置于任何user code之前,下面这张图可以表现出编译器的插码结果:

  有一些微妙的地方必须注意,编译器安插在constructor中的members声明动作是以members在class中的声明次序为根据,而不是以initializtion list中的排序为根据。如果两者在外观上错乱,很容易引起程序设计时的一些困扰或失误。例如:

class X {
public:
X(int val) : m_data2(val), m_data1(m_data2) { }
protected:
int m_data1;
int m_data2;
};

  我们很容易误以为在X constructor中是以val 设定m_data2,再将m_data2设定给m_data1.但根据两个data members的声明顺序,实际发生的动作却是:

1 X::X(int val)
2 {
3 m_data1(m_data2); // 此时 m_data2 还没有初值,糟糕
4 m_data2(val);
5 }

  于是,当我们产生一个X object:

X x(3);

  其实data members的内容可能成为这样:

x.m_data1 = -2124198216 // 这不是我们希望的
x.m_data2 = 3

一个比较好的做法是,把class X重新设计如下:

1 class X {
2 public:
3 X(int val) : m_data2(val) { m_data1 = m_data2; }
4 protected:
5 int m_data1;
6 int m_data2;
7 };

C++ 初始化列表(Initialization List)的更多相关文章

  1. C++对象模型(四):class成员初始化列表(Member Initialization List)

    本文是Inside C++ Object Model Chapter 2 部分的读书笔记. 编译器如何处理初始化成员列表的. 下列情况中,必须要使用member initialization list ...

  2. C++定义构造函数必须使用初始化列表的场合

    明其理,而知其然也. 先给理论.1. 初始化 != 赋值. a.初始化代表为变量分配内存. 变量在其定义处被编译器初始化(编译时). 在函数中, 函数参数初始化发生在函数调用时(运行时). b.赋值代 ...

  3. C++-什么时候需要在类的构造函数中使用初始化列表

    1,如果基类没有default构造函数,则意味着其不能自己初始化.如果其被派生,派生类的构造函数要负责调用基类的构造函数,并传递给它需要的参数.下例中Base 2,如果类成员没有默认构造函数.下例中E ...

  4. C++类的成员初始化列表的相关问题

    在以下四中情况下,要想让程序顺利编译,必须使用成员初始化列表(member initialization list): 1,初始化一个引用成员(reference member): 2,初始化一个常量 ...

  5. 面向对象程序设计-C++_课时13初始化列表

    构造函数设置成员初值方法有两种:一种是在函数体内赋值,另一种是采用初始化列表的形式. 初始化列表BETTER 函数体内赋值 类名::类名(形参1,形参2,...形参n) { 数据成员1=形参1; 数据 ...

  6. (C++) 初始化列表 std::initializer_list

    构造时直接使用初始化列表 T object { arg1, arg2, ... }; (1) T { arg1, arg2, ... } (2) new T { arg1, arg2, ... } ( ...

  7. [深度探索C++对象模型]关于成员初始化列表(member initiallization list)

    四种特殊情况: 1.当初始化一个reference member时. 2.当初始化一个const member时. 3.当初始化一个base class的constructor,而它拥有一组参数时. ...

  8. The Semantics of Constructors——2.4 成员初始化列表

    2.4 成员初始化列表(Member Initialization List) 当你写下一个constructor时,就有机会设定class members的初值.要不是经由member initia ...

  9. C++中使用初始化列表的情况

    http://blog.csdn.net/iceshirley/article/details/5688696 要理解这个问题,从概念上,我们要知道一点,那就是构造函数的执行过程会分成两个阶段:隐式或 ...

  10. C++11新特性——初始化列表 initializer_list

    破事水: 由于最近数据结构有个实验报告说是要对字符串进行排序,想偷个懒不想一个一个地赋值,虽然可以用strcpy和传入二级指针的形式直接写,但是这样感觉不美观漂亮. 然后就去膜了一下C++11的新特性 ...

随机推荐

  1. 【福利活动】深度体验OpenHarmony对接华为云IoT

      本文主要介绍基于OpenHarmony 3.0来接入IoTDA,以BearPi-HM_Nano开发板为例,使用huaweicloud_iot_link SDK对接华为云物联网平台的简单流程.文末为 ...

  2. 最新CAMX-python融合技术应用与大气污染来源解析方法

    大气污染问题既是局部.当地的,也是区域的,甚至是全球的.本地的污染物排放除了对当地造成严重影响外,同时还会在动力输送作用下,极大地影响下风向地区的大气环境状况.数值模式模拟是分析大气污染物时空分布和成 ...

  3. 在 macOS Big Sur 上安装 MySQL 8.x Compressed TAR Archive

    因个人能力有限,文章难免存在错误,望斧正,感谢. 版本: macOS 11.6 Intel版本 MySQL 8.0.26 Compressed TAR Archive 一.准备所需文件 前往 MySQ ...

  4. 重新整理数据结构与算法(c#)—— 算法套路分治算法[二十五]

    前言 有一个汉罗塔的游戏如下: 汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具. 大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘. 大梵天 ...

  5. 试题B:小球反弹(第十五届蓝桥杯省赛B组c/c++组)

    试题B:小球反弹 我在刷博客的时候看见有人分享了蓝桥杯的题目,我想起了我之前大学打蓝桥杯刷题的时光,还是很怀念当时打比赛的氛围,关于这个小球反弹的题目,我感觉很有意思,我一开始也是走了好多弯路,然后去 ...

  6. 力扣539(java)-最小时间差(中等)

    题目: 给定一个 24 小时制(小时:分钟 "HH:MM")的时间列表,找出列表中任意两个时间的最小时间差并以分钟数表示. 示例 1: 输入:timePoints = [" ...

  7. 力扣430(java)-扁平化多级双向链表(中等)

    题目: 你会得到一个双链表,其中包含的节点有一个下一个指针.一个前一个指针和一个额外的 子指针 .这个子指针可能指向一个单独的双向链表,也包含这些特殊的节点.这些子列表可以有一个或多个自己的子列表,以 ...

  8. POJ4151:电影节

    4151:电影节 总时间限制:  1000ms 内存限制:  65536kB 描述 大学生电影节在北大举办! 这天,在北大各地放了多部电影,给定每部电影的放映时间区间,区间重叠的电影不可能同时看(端点 ...

  9. CDN应用进阶 | 正确使用CDN 让你更好规避安全风险

    为了帮助用户更好地了解和使用CDN产品,CDN应用实践进阶系统课程开课了.12月17日,阿里云CDN产品专家彭飞在线分享了<正确使用CDN,让你更好规避安全风险>议题,内容主要包括以下几个 ...

  10. 技术干货 | 深度解构 Android 应用面临紧急发版时的救星方案:mPaaS 热修复——DexPatch

    简介: 关于 Android 热修复方案--DexPatch 的介绍与使用说明 方案介绍 为了解决 Native 模块上线后的问题,mPaaS 提供了热修复功能,实现不发布客户端 apk 场景下的热修 ...