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

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

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

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

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

构造函数提的形式为(提前声明):

this->a = vector(26)

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. c++构造函数成员初始化中赋值和初始化列表两种方式的区别

    先总结下: 由于类成员初始化总在构造函数执行之前 1)从必要性: a. 成员是类或结构,且构造函数带参数:成员初始化时无法调用缺省(无参)构造函数 b. 成员是常量或引用:成员无法赋值,只能被初始化 ...

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

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

  3. C++远航之封装篇——默认构造函数、初始化列表、拷贝构造函数

    1.默认构造函数 没有参数: 若有参数,则一定全部都有默认的参数值. 2.初始化列表 (1)概念 (2)特性 建议用初始化列表来初始化数据成员. 初始化列表先于构造函数执行: 初始化列表只能用于构造函 ...

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

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

  5. python 构造函数传参_C++和python混合编程之在python类构造函数中传参方法

    C++和python混合编程 零.前言 一.说明 二.测试代码 1.C++代码 2.python代码 三.运行结果 零.前言 C++是一门高效率的语言,Python是一门简单易学的脚本语言,现在Pyt ...

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

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

  7. c++的构造函数极其调用(无参构造函数,有参构造函数,拷贝构造函数)

    1.c++编译器会自动调用构造函数 //构造函数(与类名相同) //析构函数:没有参数也没有任何返回类型,被自动调用 #include<iostream> using namespace ...

  8. C++构造函数之初始化列表

    C++构造函数之初始化列表 构造函数可以说是对于C++每个类来说最重要的组成部分,之前也详细介绍过构造函数的相关知识,今天给构造函数进行补充,主要说明一下构造函数的初始值列表 一.初始化列表的写法 仍 ...

  9. C++简单问题搞复杂之构造函数与初始化(普通类)

    夸张一点说,C语言是最容易掌握的程序设计语言. 简单和复杂往往却没有明确的界限,比如C创建结构体后,由于分配的内存没有做任何处理,接着就是一堆赋值语句,导致代码行数激增,那些鼠标滚轮经常坏掉的程序员, ...

最新文章

  1. Flexible Box布局基础知识详解
  2. 计算机网络crc校验实验报告,CRC校验实现-实验报告(附主要实现代码)
  3. AB1601定时器timer0,timer1简介
  4. (Z)复杂繁琐的芯片设计流程
  5. SpringMVC4零配置--web.xml
  6. github 建立_建立在线社区:GitHub教师
  7. 【报告分享】2021年30+精致女性人群需求洞察:“她”经济时代科技引领精致生活.pdf(附下载链接)...
  8. 聊一聊DTM子事务屏障功能之SQL Server版
  9. vs2005创建智能设备IE脚本错误
  10. 阿法狗之后的围棋世界
  11. yml连接sqlserver_spring连接sqlserver数据库
  12. android 异步编程,flutter异步编程-事件循环、Isolate、Stream(流)
  13. 小游戏如何带动直播平台发展?
  14. python证明冰雹猜想_如果冰雹猜想被证明了。那数学会有很大突破吗?
  15. 数仓分层模型架构分享(3)
  16. !!!---1588|Sum of All Odd Length Subarrays(新)
  17. unity游戏开发之令人上瘾的6大手游设计’潜规则’
  18. 【Linux安装和更新】两种方式更换软件源,以JDK为例安装
  19. 光云电力发电领域碳排放太高,光云电力指出调整能源结构是关键一步
  20. php逆向工程实例,proe逆向工程实例分析

热门文章

  1. ADC采集数据(DMA模式)
  2. python异常处理输入不是整数_Python异常处理(二)
  3. iphone学习笔记(一)
  4. springboot批量更新实体_mybatis+mysql+springboot批量插入,批量更新数据
  5. 几款主流在线输入法评测
  6. FTP文件传输服务器(详解)
  7. python_opencv人脸检测
  8. 前端实验六——英汉字典
  9. sql事务(Transaction)用法介绍及回滚实例
  10. TP5 model 模型事件