对于常量类型和引用类型的数据成员,不能在构造函数中用赋值语句直接赋值,C++提供初始化表进行置初值。

带有成员初始化表的构造函数的一般形式如下:

类名::构造函数名([参数表])[:(成员初始化表)]

{

// 构造函数体

}

         成员初始化表的一般形式为:

数据成员名1(初始值1),数据成员名2(初始值2),……

C++构造函数中初始化成员参数列表初始化成员(必须用的原因:对象成员的初始化,const修饰的成员的初始化,引用成员的初始化,子类调用父类的构造函数初始化父类成员)参数列表在构造函数执行之前执行,参数列表中执行的是初始化(所有的成员,无论是否出现在参数列表中,都会有初始化),参数列表的执行顺序与类中成员的声明顺序,与类的继承顺序相一致构造函数中执行的一般是赋值多重继承,虚继承构造函数的参数初始化列表的区别

类对象的构造顺序:

1.分配内存,调用构造函数时,隐式/显示的初始化各数据成员;

2.进入构造函数后在构造函数中执行一般赋值与计算。

使用初始化列表有两个原因:

原因1.必须这样做:

以下三种情况下需要使用初始化成员列表:

一、需要初始化的数据成员是对象的情况(这里包含了继承情况下,通过显示调用父类的构造函数对父类数据成员进行初始化);

二、需要初始化const修饰的类成员;

三、需要初始化引用成员数据;

例一、数据成员是对象,且对象只有含参数的构造函数;

如果我们有一个类成员,它本身是一个类或者是一个结构,而且这个成员它只有一个带参数的构造函数,而没有默认构造函数,这时要对这个类成员进行初始化,就必须调用这个类成员的带参数的构造函数,如果没有初始化列表,那么他将无法完成第一步,就会报错。

class Test
{
public:Test(int x,int y,int z);
private:int a;int b;int c;
};
class MyTest
{
public:MyTest():test(1,2,3){}        //初始化,初始化列表在构造函数执行前执行(这个可以测试,对同一个变量在初始化列表和构造函数中分别初始化,首先执行参数列表,后在函数体内赋值,后者会覆盖前者)。
private:Test test;            //声明
};

因为Test有了显示的带参数的构造函数,那么他是无法依靠编译器生成无参构造函数的,所以没有三个int型数据,就无法创建Test的对象。

Test类对象是MyTest的成员,想要初始化这个对象test,那就只能用成员初始化列表,没有其他办法将参数传递给Test类构造函数。

例二、对象引用或者cosnt修饰的数据成员

另一种情况是这样的:当类成员中含有一个const对象时,或者是一个引用时,他们也必须要通过成员初始化列表进行初始化,因为这两种对象要在声明后马上初始化,而在构造函数中,做的是对他们的赋值,这样是不被允许的。

class Test
{priate:const int a;   //const成员声明public:Test():a(10){}  //初始化
};
或
class Test
{private:int &a;   //声明public:Test(int a):a(a){}  //初始化
}

例三、子类初始化父类的私有成员,需要在(并且也只能在)参数初始化列表中显示调用父类的构造函数,如下:

class Test
{private:int a;int b;int c;public:Test(int a,int b,int c){this->a = a;this->b = b;this->c = c;}int getA(){return a;}int getB(){return b;}int getC(){return c;}
};
class MyTest:public Test
{private:int d;public:MyTest(int a,int b,int c,int d):Test(a,b,c)//MyTest(int a,int b,int c,int d){ //Test(a,b,c);   //构造函数只能在初始化列表中被显示调用,不能在构造函数内部被显示调用this->d = d;}int getD(){return d;}
}; int main(int argc,char *argv[])
{MyTest mytest(1,2,3,4);printf("a=%d,b=%d,c=%d,d=%d\n",mytest.getA(),mytest.getB(),mytest.getC(),mytest.getD());return 0;
}

        多重继承,虚继承构造函数的参数初始化列表的区别:

代码如下:

注意多重继承子类的构造函数

#include <stdio.h>class CTop
{
private:int a;
public:int getA(){return a;}CTop(int a){this->a  = a;}
};class CLeft:public CTop
{
private:int b;
public:int getL(){return b;}CLeft(int a,int b):CTop(a){this->b = b;}
};class CRight:public CTop
{
private:int c;
public:int getR(){return c;}CRight(int a,int c):CTop(a){this->c = c;}
};class Test:public CLeft,public CRight
{
private:int d;
public:int getT(){return d;}Test(int a,int b,int c,int d):CLeft(a,b),CRight(a,c){this->d = d;}
};int main(int argc,char *argv[])
{Test obj(1,2,3,4);printf("obj.a=%d,obj.b=%d,obj.c=%d,obj.d=%d\n",obj.CLeft::getA(),obj.getL(),obj.getR(),obj.getT());   //getA有歧义,要用类名来做区分。return 0;
}

    注意虚继承子类的构造函数

#include <stdio.h>class CTop
{
private:int a;
public:int getA(){return a;}CTop(int a){this->a  = a;}
};class CLeft:virtual public CTop
{
private:int b;
public:int getL(){return b;}CLeft(int a,int b):CTop(a){this->b = b;}
};class CRight:virtual public CTop
{
private:int c;
public:int getR(){return c;}CRight(int a,int c):CTop(a){this->c = c;}
};class Test:public CLeft,public CRight
{
private:int d;
public:int getT(){return d;}Test(int a,int b,int c,int d):CLeft(a,b),CRight(a,c),CTop(a){this->d = d;}
};int main(int argc,char *argv[])
{Test obj(1,2,3,4);printf("obj.a=%d,obj.b=%d,obj.c=%d,obj.d=%d\n",obj.getA(),obj.getL(),obj.getR(),obj.getT());      //因为采用虚基类,虚继承机制保证了a只有一份,所以不存在歧义。return 0;
}

  原因2.效率要求这样做:

类对象的构造顺序显示,进入构造函数体后,进行的是计算,是对成员变量的赋值操作,显然,赋值和初始化是不同的,这样就体现出了效率差异,如果不用成员初始化类表,那么类对自己的类成员分别进行的是一次隐式的默认构造函数的调用,和一次赋值操作符的调用,如果是类对象,这样做效率就得不到保障。

注意:构造函数需要初始化的数据成员,不论是否显示的出现在构造函数的成员初始化列表中,都会在该处完成初始化,并且初始化的顺序和其在类中声明时的顺序是一致的,与列表的先后顺序无关,所以要特别注意,保证两者顺序一致才能真正保证其效率和准确性。

为了说明清楚,假设有这样一个类:

class foo{private :int a, b;
};

1、foo(){}和foo(int i = 0){}都被认为是默认构造函数,因为后者是默认参数。两者不能同时出现。

2、构造函数列表的初始化方式不是按照列表的的顺序,而是按照变量声明的顺序。比如foo里面,a在b之前,那么会先构造a再构造b。所以无论foo():a(b + 1), b(2){}还是foo():b(2),a(b+1){}都不会让a得到期望的值。

3、构造函数列表能够对const成员初始化。比如foo里面有一个int const c;则foo(int x) : c(x){}可以让c值赋成x。

不过需要注意的是,c必须在每个构造函数(如果有多个)都有值。

4、在继承里面,只有初始化列表可以构造父类的private成员(通过显示调用父类的构造函数)。比如说:

class child : public foo
{
};
foo里面的构造函数是这样写的:foo (int x)
{a = x;
}.

而在child里面写child(int x){ foo(x); }是通过不了编译的。

只有把子类构造函数写作child (int x) : foo(x){}才可以。

C++构造函数的参数初始化表相关推荐

  1. [置顶] 第五周项目一构造函数————4)参数初始化表

    /* [项目1]设计三角形类,通过增加构造函数,使对象在定义时能够进行初始化 * 程序的版权和版本声明部分 * Copyright (c)2012, 烟台大学计算机学院学生 * All rightsr ...

  2. 派生类参数初始化列表和基类构造函数顺序

    今天被问到了一个问题,随便回了一句,父类还没有构建,怎么能初始化父类的成员. 派生类构造函数的参数初始化列表,为什么不能初始化基类的成员? 例如下面的是不可以的 class Rectangle : p ...

  3. 构造函数及其参数列表初始化问题

    关于C++中的类的封装,如何进行封装?怎么样更好的封装?下面仅就构造函数的初始化问题进行细致分析: 类的构造函数及参数初始化列表_基本成员 #include <iostream> usin ...

  4. 不存在从node到node*的适当转换函数_C++构造函数和初始化表

    构造函数和初始化表 1 构造函数 当类对象被创建时,编译系统对象分配内存空间,并自动调用该构造函数,由构造函数完成成员的初始化工作,因此构造函数的作用是初始化对象的数据成员. 2 构造函数可以重载 构 ...

  5. c++ loadlibrary 初始化对象_C++构造函数和初始化表

    构造函数和初始化表 1 构造函数 当类对象被创建时,编译系统对象分配内存空间,并自动调用该构造函数,由构造函数完成成员的初始化工作,因此构造函数的作用是初始化对象的数据成员. 2 构造函数可以重载 构 ...

  6. 第十四章 构造函数和初始化表

    十四.构造函数和初始化表 1.构造函数和普通函数类似,也可以重载或带有缺省参数: 05constructor.cpp class Student{public:Student(const string ...

  7. 验证 Boost.Optional 复制构造函数不会尝试调用从模板化参数初始化构造函数的元素类型

    验证 Boost.Optional 复制构造函数不会尝试调用从模板化参数初始化构造函数的元素类型 实现功能 C++实现代码 实现功能 验证 Boost.Optional 复制构造函数不会尝试调用从模板 ...

  8. 【C++】类的成员初始化表与构造函数内赋值操作

    我们常常在初始化类数据成员的时候,对使用初始化表和在构造函数中十分困惑,这二者有什么区别呢?我们应该如何选择呢? 先举个简单的例子,看下面的两段代码: 代码A: inline Account::Acc ...

  9. C++学习总结12--构造函数和成员初始化表

    小记:静默如初,安之若素 1 构造函数 1. 构造函数和普通函数类似,也可以重载或带有缺省参数. 1 #include <iostream>2 using namespace std;3 ...

最新文章

  1. ActiveMQ消息存储持久化
  2. 都2020年,开发制作微信小程序商城,需要准备什么资料?应该不会不知道吧!
  3. c语言时间库函数#includetime.h
  4. nginx 修复固定链接404
  5. 无线路由器说说2.4G和5G Wi-Fi的区别
  6. 数据中心母线布置方式
  7. Windows下UltraEdit查看Objective-C代码高亮工具
  8. 关于python中带下划线的变量和函数 的意义
  9. n维椭球体积公式_加速度计 椭球校准 (最小二乘法 椭球拟合)
  10. 1941套站点模版,终生收藏,个个精品
  11. [Bzoj3262]陌上花开(CDQ分治树状数组||树套树)
  12. Web接入QQ登陆简单入门操作
  13. plsql:导出数据到excel
  14. AXURE原型设计经验总结
  15. 坦克世界因计算机丢失,坦克世界新版本上线在即,玩家必须知道的几件事。
  16. html修改成透明色,在html2canvas中将透明颜色更改为白色
  17. “穿搭速递”首页制作
  18. php 统计 app 下载量,如何做一个算法估算出一个不定时抓取到一个APP每天的下载量...
  19. 闪客工具:greensock出的TransformManager类
  20. 抓包软件抓取手机数据(app,浏览器等)

热门文章

  1. IDEA 中取消下面的按钮即可显示定位的按钮圆圈
  2. SQL联合查询实现统计功能
  3. 【数据结构】(图解)leetcode刷题之单链表(中)
  4. 微信公众号缓存的问题
  5. 自定义elementui上传文件以及携带参数
  6. Powers of i in Complex Numbers
  7. mysql笛卡尔积的过程
  8. 程序员没对象,是不想找还是真的找不到?
  9. C语言中 extern 的使用
  10. nashorn_Nashorn简介